Linux操作系统-标准IO库(3)

来源:互联网 发布:js点击图片全屏显示 编辑:程序博客网 时间:2024/05/20 03:38

Linux操作系统—标准IO库(3)(2015-8-5)

分类:Linux操作系统

二进制IO和定位流

  二进制I/O也称直接I/O,一个一个对象的I/O,面向记录的I/O或面向结构的I/O。每次I/O操作读取或写一定数量的对象,而每个对象具有指定的长度。常用于二进制文件中读或向二进制文件中写一个结构。

读取二进制流

  使用fread函数可以进行二进制数据的读取。

#include <stdio.h>size_t fread(void *ptr, size_t size, size_t nitems, FILE *stream);

  函数fread的各参数和返回值的含义如下:
1. ptr:输入缓存
2. size:数据块的大小
3. nitems:数据块的个数
4. stream:流文件指针
5. 返回值:返回实际读取到的数据块的个数。如果次数字小于nitems,则表示出错或到达文件尾端,应调用ferror或feof以判断究竟是哪一种情况

  这个函数参数有点多,还是找一个使用的例子来看看

nRead = fread(buf, sizeof(unsigned char), BUFFSIZE, fpIn);

  这一小段代码的作用是:调用fread函数从源文件中读取BUFFSIZE各字节。fpIn是源文件的流指针,BUFFSIZE是数据块的个数,sizeof(unsigned char)是数据块的大小,也即是一个字符的大小,buf是输入的缓存,也即是fread读取的数据存放的地方。fread返回的是实际读取的字符数,该数值被记录在了变量nRead中。
  实际读取的数据块的个数nRead如果小于预定的BUFFSIZE,则表示出错或者到达文件尾端,应调用ferror或feof以判断究竟是哪中情况。

写二进制流

  使用fwrite函数可以进行二进制数据块的输出。

#include <stdio.h>size_t fwrite(const void *ptr, size_t size, size_t nitems, FILE *stream);

  函数fwrite的各参数和返回值的含义如下:
1. ptr:待输出的数据的
2. size:数据块的大小
3. nitems:数据块的个数
4. stream:流文件的指针
5. 返回值:返回实际输出的数据块的个数,如果小于nitems,则表示出错。

  总结这两个函数(不严谨,但可以这样区分两者):
- fread:从stream流中读取数据存入ptr中
- fwrite:从ptr总读取数据存入stream中

二进制I/O的常见用法

  • 读或写一个二进制数组。例如:
float data[10]...if (fwrite(&data[2], sizeof(float), 4, fp) !=  4)    printf("fwrite error.\n");

  这段代码调用fwrite向文件流写入data数组从第3个元素起的连续4个元素,每个数据块的大小为一个元素(一个浮点数)的大小,如果写入的元素个数不为4,则说明发生了错误。

  • 读或写一个结构。此时,指定size为结构体的大小,nitems指定为1。例如:
struct {    short count;    long total;    char name[NAMESIZE];}item;...if (fwrite(&item, sizeof(item), 1, fp) != 1)    printf("fwrite error");

  这段代码盗用fwrite向文件流写入结构体变量item,数据块为1,返回值如果不为1,则说明发生了错误。

  • 以上二者的结合。如:向一个结构体数组内写数据。

二进制I/O实践篇

目标:实现简单的问价复制功能

#include <stdio.h>#include <stdlib.h>#define     BUFFSIZE    80  int main(int argc, char *argv[]){    FILE *fpIn, *fpOut;    int nRead, nWrite;    unsigned char buf[BUFFSIZE];    if (argc != 3){         /* 如果从命令行传递过来的参数的个数不是3个 */                                                  printf("Usage : %s <source_file> <destination_file>\n", argv[0]);        return -1;    }                            /* 如果要被复制的文件无法打开被读取 */    if ((fpIn = fopen(argv[1], "r")) == NULL){        printf("Cannot open file [%s] for reading.\n", argv[1]);        return -1;    }                            /* 如果复制过来的新文件无法打开被写入 */    if ((fpOut = fopen(argv[2], "w")) == NULL){        printf("Cannot open file [%s] for writing.\n", argv[2]);        return -1;    }                            /* 当要被复制的文件没有到达文件尾时 */    while (!feof(fpIn)){        nRead = fread(buf, sizeof(unsigned char), BUFFSIZE, fpIn);        if (nRead < BUFFSIZE){            if (ferror(fpIn)){              /* 如果读取出错了 */                printf("Copy failed.\n");                break;            }        }        if (nRead > 0){                     /* 进行复制操作 */            nWrite = fwrite(buf, sizeof(unsigned char), nRead, fpOut);            if (nWrite != nRead){           /* 如果复制出错了 */                printf("Copy failed.\n");                break;            }        }    }    fclose(fpOut);                          /* 将文件关闭 */    fclose(fpIn);    return 0;}

  编译并运行

biantiao@lazybone1994-ThinkPad-E430:~/桌面$ gcc -o ioCopy ioCopy.cbiantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./ioCopyUsage : ./ioCopy <source_file> <destination_file>biantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./ioCopy a.txt b.txtCannot open file [a.txt] for reading.biantiao@lazybone1994-ThinkPad-E430:~/桌面$ touch a.txtbiantiao@lazybone1994-ThinkPad-E430:~/桌面$ ./ioCopy a.txt b.txtbiantiao@lazybone1994-ThinkPad-E430:~/桌面$ lsa.txt  b.txt  ioCopy  ioCopy.cbiantiao@lazybone1994-ThinkPad-E430:~/桌面$

  你可以发现参数argv[0]不是ioCopy而是./ioCopy,如果你不想在运行时加入./,就把ioCopy程序文件放入bin目录下好了。

定位流

  可以调用fseek来定位流文件的读写指针。

#include <stdio.h>int fseek(FILE *stream, long offset, int whence);

  函数fseek的各参数和返回值的含义如下:
1. stream:流文件的指针
2. offset:位移量
3. whence:指定位移量相对于何处开始。whence可以取如下三个常量

  • SEEK_SET:文件开始位置
  • SEEK_CUR:文件指针当前位置
  • SEEK_END:未见结束位置

4 返回值:成功返回0,失败返回-1,错误记录在errno

  一次成功的调用ftell()会清除流结束标志,并会撤销已调用的ungetc()对流的影响。调用rewind()函数可以将一个流的读写指针设置到文件的起始位置。其原型如下:

#include <stdio.h>void rewind(FILE *stream);

  该函数的唯一参数是已打开流的流文件指针。调用rewind(fp)基本等同于调用fseek(stream, 0L, SEEK_SET)。稍微不同的是,rewind函数将在读写指针设置到文件的起始位置时同时会将出错指示errno清0
  调用ftell()函数可以获得一个流的读写指针的当前位置。该函数的原型如下:

#include <stdio.h>long ftell(FILE *stream);

  该函数返回读写指针当前相对于文件起始位置的位移量;若出错,则返回-1,错误记录在errno中。

0 0
原创粉丝点击