参考: http://blog.csdn.net/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()的结果也可以说明这点)。