参考: http://blog.youkuaiyun.com/dreamtdp/article/details/7560654
1. fopen, fread, fwrite是ANSI C的标准库,open, read, write是UNIX下的系统调用(WINDOWS下分别为_open, _read, _write);
2. fread, fwrite带缓冲功能,底层也是通过read,write实现的;
例如: 如果文件大小是8k。 如果用read/write,且只分配了2k的缓存,则将此文件读出/写入需要做4次系统调用来实际操作磁盘读写;
如果用fread/fwrite,系统自动非配缓存,则读出/写入此文件只需要一次系统调用,效率比read/write要高4倍。
3. 由于f族函数是标准库的内容,因此更具移植性;
4. 测试代码:
#define _CRT_SECURE_NO_WARNINGS
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <windows.h>
#include <fcntl.h>
#include <io.h>
const int COUNT = 10000;
const int BSIZE = 100;
const int BUFSIZE = COUNT*BSIZE;
/*
测试0: 使用fread()读文件
*/
LONGLONG test0()
{
FILE * rFile;
rFile = fopen("X:\\标准媒体测试库\\Video\\MKV\\功夫熊猫.mkv", "rb");
if (NULL == rFile)
{
return 0;
}
UINT8* buf = (UINT8*)malloc(BUFSIZE);
memset(buf, 0, BUFSIZE);
UINT8* dst = buf;
LARGE_INTEGER nLastTime1, nLastTime2, timeDelt;
QueryPerformanceCounter(&nLastTime1);
for (int i = 0; i < COUNT; ++i)
{
fread(dst, 1, BSIZE, rFile);
dst += BSIZE;
}
QueryPerformanceCounter(&nLastTime2);
timeDelt.QuadPart = nLastTime2.QuadPart - nLastTime1.QuadPart;
fclose(rFile);
free(buf);
return timeDelt.QuadPart;
}
/*
测试1: 使用_read()读文件
*/
LONGLONG test1()
{
int handle = _open("X:\\标准媒体测试库\\Video\\MKV\\gf.mkv", O_RDONLY | O_BINARY);
if (0 == handle)
{
return 0;
}
UINT8* buf = (UINT8*)malloc(BUFSIZE);
memset(buf, 0, BUFSIZE);
UINT8* dst = buf;
LARGE_INTEGER nLastTime1, nLastTime2, timeDelt;
QueryPerformanceCounter(&nLastTime1);
for (int i = 0; i < COUNT; ++i)
{
_read(handle, dst, BSIZE);
dst += BSIZE;
}
QueryPerformanceCounter(&nLastTime2);
timeDelt.QuadPart = nLastTime2.QuadPart - nLastTime1.QuadPart;
_close(handle);
free(buf);
return timeDelt.QuadPart;
}
/*
测试2: 使用fread()读取大量数据
*/
LONGLONG test2()
{
FILE * rFile = fopen("X:\\标准媒体测试库\\Video\\MKV\\10036200.mkv", "rb");
if (NULL == rFile)
{
return 0;
}
UINT8* buf = (UINT8*)malloc(BUFSIZE);
memset(buf, 0, BUFSIZE);
LARGE_INTEGER nLastTime1, nLastTime2, timeDelt;
QueryPerformanceCounter(&nLastTime1);
fread(buf, 1, BUFSIZE, rFile);
QueryPerformanceCounter(&nLastTime2);
timeDelt.QuadPart = nLastTime2.QuadPart - nLastTime1.QuadPart;
fclose(rFile);
free(buf);
return timeDelt.QuadPart;
}
/*
测试3: 使用_read()读取大量数据
*/
LONGLONG test3()
{
int handle = _open("X:\\标准媒体测试库\\Video\\MKV\\h264_I26_DP_HD10_profile_incomp_level41_00_9900Kbps_30fps.mkv", O_RDONLY | O_BINARY);
if (0 == handle)
{
return 0;
}
UINT8* buf = (UINT8*)malloc(BUFSIZE);
memset(buf, 0, BUFSIZE);
LARGE_INTEGER nLastTime1, nLastTime2, timeDelt;
QueryPerformanceCounter(&nLastTime1);
_read(handle, buf, BUFSIZE);
QueryPerformanceCounter(&nLastTime2);
timeDelt.QuadPart = nLastTime2.QuadPart - nLastTime1.QuadPart;
_close(handle);
free(buf);
return timeDelt.QuadPart;
}
int main()
{
LONGLONG t0 = test0();
LONGLONG t1 = test1();
LONGLONG t2 = test2();
LONGLONG t3 = test3();
}
调整BSIZE的大小,可以看到fread()每次读取不同数据的情况下对效率的提升,以下是我电脑上的一些数据:
BSIZE为10时: t0: 3888, t1: 120309
BSIZE为100时: t0: 8091, t1: 165177
BSIZE为1000时: t0: 776628, t1: 751736
BSIZE为3000时: t0: 2200077, t1: 2209207
由上可知,当每次读取的数据较小时,fread()能显著提高性能,但若每次读的数据较大,则read()有微弱优势(test2()和test3()的结果也可以说明这点)。