二进制I/O、刷新和定位函数

二进制I/O

把数据写入到文件效率最高的方法是用二进制形式写入。二进制输出避免了在 数值转换为字符串过程中涉及的开销和精度损失。

fread函数用于读取二进制数据,fwrite用于写入二进制数据。 

size_t fread(void *buffer, size_t size, size_t count, FILE *stream);
size_t fwrite(void *buffer, size_t size, size_t count, FILE *stream);

buffer是一个指向用于保存数据的内存位置的指针,size是缓冲区中每个元素的字节数,count是读取或写入的元素数,stream是数据读取或写入的流。

函数返回值是实际读取或写入的元素(非字节)数目。如果输入遇到文件尾或输出出现错误,这个数字可能比请求的元素数要小。

刷新和定位函数

刷新

有时候用户程序希望把I/O缓冲区中的数据立刻传给内核,让内核写回设备,这称为Flush操作,对应的库函数是fflushfclose函数在关闭文件之前也会做Flush操作。

fflush它迫使一个输出流的缓冲区内的数据进行物理写入,不管它是不是已经写满。 

int fflush(FILE *stream);

例如,调用fflush保证调试信息实际打印出来,而不是保存在缓冲区直到以后才打印。

一般后面写入的数据在文件中的位置是以前所有写入数据的后面。C同时支持随机访问I/O,通过在读取或写入先前定位到文件中需要的位置来实现。

定位 

long ftell(FILE *stream);
int fseek(FILE *stream, long offset, int from);

ftell函数返回流当前位置,也就是,下一个读取或写入将要开始的位置距离起始位置的偏移量。在二进制流中,这个值就是当前位置距离文件其实位置之间的字节数。

ftell的返回值总是可以用于fseek函数中,作为距离起始位置偏移量。

定位到文件尾之后并进行写入将扩展这个文件。定位到文件尾之后并进行读取将导致返回一条“到达文件尾”的消息。在二进制中,从SEEK_END进行定位可能不被支持。在文本流,如果from是SEEK_CUR或SEEK_END,offset必须是零。如果from是SEEK_SET,offset必须是一个从同一个流中以前调用ftell返回的值。

符号

定位

SEEK_SET

从流起始位置起offset个字节,offset非负值。

SEEK_CUR

从流当前位置起offset个字节,offset可正可负。

SEEK_END

从流尾部位置起offset个字节,offset可正可负。如果正只,定位到文件尾的后面。

offset可正可负,负值表示向前(向文件开头的方向)移动,正值表示向后(向文件末尾的方向)移动,如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了文件末尾,再次写入时将增大文件尺寸,从原来的文件末尾到fseek移动之后的读写位置之间的字节都是0

用fseek改变流的位置副作用:

1.行末指示字符被清除。

2.如果在fseek之前使用ungetc,那么这个退回的字符会丢弃。

其他函数,限制更严: 

void rewind(FILE *stream);
int fgetpos(FILE *stream, fpos_t *position);
int fsetpos(FILE *stream, fpos_t const *position);

rewind函数将读/写指针设置回指定流的起始位置,同时清除流的错误提示标志。

fgetpos和fsetpos分别是ftell和fseek的替代方案,fgetpos用一个指向fpos_t的指针存储文件的当前位置,fsetpos把文件位置设置为存储在这个位置的值。

posted @ 2018-04-05 17:31  刘-皇叔  阅读(418)  评论(0编辑  收藏  举报