二进制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操作,对应的库函数是fflush, fclose函数在关闭文件之前也会做Flush操作。
fflush它迫使一个输出流的缓冲区内的数据进行物理写入,不管它是不是已经写满。
int fflush(FILE *stream);
例如,调用fflush保证调试信息实际打印出来,而不是保存在缓冲区直到以后才打印。
定位
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把文件位置设置为存储在这个位置的值。