当前位置: 首页 > 工具软件 > fwrite > 使用案例 >

c语言缓存大小 fwrite,fread和fwrite函数,C语言fread和fwrite函数详解

濮阳钟展
2023-12-01

对文件格式化读写函数 fprintf 与 fscanf 而言,尽管它可以从磁盘文件中读写任何类型的文件,即读写的文件类型可以是文本文件、二进制文件,也可以是其他形式的文件。但是,对二进制文件的读写来说,考虑到文件的读写效率等原因,还是建议尽量使用 fread 和 fwrite 函数进行读写操作。

fread 与 fwrite 函数的原型如下面的代码所示:

size_t fread(void *buf, size_t size, size_t count, FILE *fp);

size_t fwrite(const void * buf, size_t size, size_t count, FILE *fp);

在上面的 fread 和 fwrite 函数原型中:

参数 size 是指单个元素的大小(其单位是字节而不是位,例如,读取一个 int 型数据就是 4 字节);

参数 count 指出要读或写的元素个数,这些元素在 buf 所指的内存空间中连续存放,共占“size*count”个字节。

即 fread 函数从文件 fp 中读出“size*count”个字节保存到 buf 中,而 fwrite 把 buf 中的“size*count”个字节写到文件 fp 中。最后,函数 fread 和 fwrite 的返回值为读或写的记录数,成功时返回的记录数等于 count 参数,出错或读到文件末尾时返回的记录数小于 count,也可能返回 0。

需要注意的是,尽管 fread 和 fwrite 函数可以对数据进行成块读写,但并不是说一次想读写多少数据就能全部读写多少数据,毕竟缓存有限,而且不同的操作系统的缓存大小也可能不一样。同时,许多程序员还认为函数的参数 (size、count) 与位置对齐有关,甚至认为语句“fwrite(ptr,1,1024,fp)”的执行效率会比“fwrite(ptr,1024,1,fp)”高。实际情况并非如此,如在 glibc-2.17 库中对 fwrite 函数的实现如下:

_IO_size_t _IO_fwrite (const void *buf, _IO_size_t size, _IO_size_t count, _IO_FILE *fp)

{

_IO_size_t request = size * count;

_IO_size_t written = 0;

CHECK_FILE (fp, 0);

if (request == 0)

return 0;

_IO_acquire_lock (fp);

if (_IO_vtable_offset (fp) != 0 || _IO_fwide (fp, -1) == -1)

written = _IO_sputn (fp, (const char *0 buf, request);

_IO_release_lock (fp);

if (written == request)

return count;

else if (written == EOF)

return 0;

else

return written / size;

}

从上面的 fwrite 函数源码实现中可以清楚地看到:

首先,在把参数 size 与 count 传进函数之后,第一步就是通过语句“_IO_size_t request=size*count;”来计算“size*count”,所以这两个参数与什么位置对齐根本没有半点关系。

其次,在函数返回时,如果整个写入成功(“written==request”),就返回 count;如果遇到 EOF(“written==EOF”),就返回 0;否则返回“written/size”。由此可见,函数返回的是成功写入的块数,而不是字节数(除非 size 为 1),这样做有许多好处。例如,在写入多个结构体时,返回值能告诉你成功写入的结构体的个数。当然,这样看来,前面的“fwrite(ptr,1,1024,fp)”与“fwrite(ptr,1024,1,fp)”语句还是有所差别的。但是,如果调用者只关心是否全部写入成功,那么就完全没必要纠结于语句“fwrite(ptr,1,1024,fp)”与“fwrite(ptr,1024,1,fp)”之间的差别了。

对于 fread 函数,其道理与 fwrite 函数完全一样,如下面的函数源代码所示:

_IO_size_t _IO_fread (void *buf,_IO_size_t size,_IO_size_t count,_IO_FILE *fp)

{

_IO_size_t bytes_requested = size * count;

_IO_size_t bytes_read;

CHECK_FILE (fp, 0);

if (bytes_requested == 0)

return 0;

_IO_acquire_lock (fp);

bytes_read = _IO_sgetn (fp, (char *) buf, bytes_requested);

_IO_release_lock (fp);

return bytes_requested == bytes_read ? count : bytes_read / size;

}

除此之外,函数 fwrite 还与文件的打开模式有关。例如,如果文件的打开模式是“w+”,则是从文件指针指向的地址开始写,替换掉之后的内容,文件的长度可以不变,fp 的位置移动 count 个数;如果文件的打开模式为“a+”,则从文件的末尾开始添加,文件的长度会不断增加。

 类似资料: