fread与read的区别

fread和read分别是ANSI C标准库和UNIX系统调用。fread带有缓冲功能,通常比read更高效,尤其在处理小数据块时。然而,当读取大数据块时,read的性能可能略微优于fread。测试显示,随着每次读取数据量的增加,fread的性能优势逐渐减小。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值