fread与read的区别

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


你可能感兴趣的:(fread与read的区别)