使fread和fwrite的运用更加的强壮

在很多人的代码中,我们会发现很多这样的代码
char buf[ 1024 ];
int len = 0;
...
fread( buf, len,  sizeof( char ), file1 );

...
fwrite( buf, len, sizeof( char ), file2 );

在正常情况下,这些代码能够正常的运行,但是在某些特殊点程序将出现错误。
我们知道fread和fwrite能够被信号中断,如果信号中没有设置SA_RESTART,那么结果无法确定。
那么如何是上面的操作更加的强壮呢?下面我简单的演示一下实现的方式,希望大家日后尽量使用这种方式来进行读写:-)。
size_t loaded = fread( buf, len, sizeof( char ), file1 );
然后按照loaded来确定真正的读入字节。有些网友可能喜欢这么写
while ( (loaded = fread( buf, len, sizeof( char ), file1 )) > 0 )
{
    // do something
}
其实犯的错误也是忽略了信号对fread函数的影响,在信号存在下,loaded可能是0。所以我们应该最好检测是否是中断引起的问题。
while ( !feof( file1 ) )
{
   loaded = fread( buf, len, sizeof( char ), file1 );
   //do something
}

对于fwrite的使用,也是类似的方法。
for ( int off = 0; off < len; )
{
  off += (int) fwrite( buf + off, len - off, sizeof( char ), file2 );
}

这样做看上去好像有些傻瓜,但是对于程序的强壮而言是非常卓越的,希望大家日后尽量这么做!

本文也将提供两个比较规范的程序实现,希望有所帮助!
size_t readn( void *buf, size_t itemSize, size_t items, FILE *fd )
{
    size_t loaded = 0;
    size_t count;

    // Check parameters
    assert( buf != NULL );
    assert( itemSize > 0 );
    assert( items > 0 );
    assert( fd != NULL );

    // Load requesting data
    while ( (count = fread( buf, itemSize, items, fd )) < items )
    {
        loaded += count;
        if ( ferror( fd ) || feof( fd ) )
            return loaded;
        buf     = ((char *) buf) + itemSize * count;
        items  -= count;
    }

    loaded += count;

    return loaded;
}

size_t writen( const void *buf, size_t itemSize, size_t items, FILE *fd )
{
    size_t saved = 0;
    size_t count;

    // Check parameters
    assert( buf != NULL );
    assert( itemSize > 0 );
    assert( items > 0 );
    assert( fd != NULL );

    // Save requesting data
    while ( (count = fwrite( buf, itemSize, items, fd )) < items )
    {
        saved  += count;
        if ( ferror( fd ) )
            return saved;
        buf     = ((char *) buf) + itemSize * count;
        items  -= count;
    }
   
    saved += count;

    return saved;
}

鉴于网友的讨论,我觉得下面的方法在某些情况下可能会更好一些,但是他有一个很重要的问题,就是无法通过中断信号来将读写阻塞调用中止。从我个人角度来看,还是直接使用read和write函数比较直观。特别是在linux或者unix系统中。
size_t readn( void *buf, size_t itemSize, size_t items, FILE *fd )
{
    size_t loaded = 0;
    size_t count;

    // Check parameters
    assert( buf != NULL );
    assert( itemSize > 0 );
    assert( items > 0 );
    assert( fd != NULL );

    // Load requesting data
    while ( (count = fread( buf, itemSize, items, fd )) < items )
    {
        loaded += count;
        if ( feof( fd ) )
            return loaded;
        if ( ferror( fd ) && errno != EINTR )
            return loaded;
        buf     = ((char *) buf) + itemSize * count;
        items  -= count;
    }

    loaded += count;

    return loaded;
}

size_t writen( const void *buf, size_t itemSize, size_t items, FILE *fd )
{
    size_t saved = 0;
    size_t count;

    // Check parameters
    assert( buf != NULL );
    assert( itemSize > 0 );
    assert( items > 0 );
    assert( fd != NULL );

    // Save requesting data
    while ( (count = fwrite( buf, itemSize, items, fd )) < items )
    {
        saved  += count;
        if ( ferror( fd ) && errno != EINTR )
            return saved;
        buf     = ((char *) buf) + itemSize * count;
        items  -= count;
    }
   
    saved += count;

    return saved;
}

补充一下,在win32系统中,我们一定要定义_MT,否则errno不是多线程安全的。
在unix或者linux系统中最好定义 _LIBC_REENTRANT或者 _REENTRANT宏,这样能够确保errno一定是多线程安全的。当然,在大多数情况下,默认都是多线程安全的。
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
freadfwrite是C语言中用于文件读写的函数。它们可以用来读写任何类型的文件,包括文本文件和二进制文件。[1]对于二进制文件的读写操作,建议使用freadfwrite函数,因为它们可以提高读写效率。[1] fread函数用于从文件中读取数据。它的参数包括要读取的数据存储的位置(缓冲区指针)、每个数据项的大小、要读取的数据项的数量以及要读取的文件指针。fread函数会从文件中读取"size*count"个字节,并将其保存到缓冲区中。[3]函数的返回值是成功读取的记录数,如果出错或读到文件末尾,返回的记录数可能小于count,甚至可能返回0。[3] fwrite函数用于向文件中写入数据。它的参数包括要写入的数据存储的位置(缓冲区指针)、每个数据项的大小、要写入的数据项的数量以及要写入的文件指针。fwrite函数会将缓冲区中的"size*count"个字节写入文件中。[3]函数的返回值是成功写入的记录数,如果出错,返回的记录数可能小于count。[3] 需要注意的是,尽管freadfwrite函数可以进行成块读写,但并不是说一次想读写多少数据就能全部读写多少数据,因为缓存有限,而且不同操作系统的缓存大小可能不一样。[2]此外,有些程序员认为函数的参数(size、count)与位置对齐有关,甚至认为语句"fwrite(ptr,1,1024,fp)"的执行效率会比"fwrite(ptr,1024,1,fp)"高,但实际情况并非如此。[2] 总结起来,freadfwrite是C语言中用于文件读写的函数,可以读写任何类型的文件。对于二进制文件的读写操作,建议使用freadfwrite函数。fread函数从文件中读取数据,fwrite函数向文件中写入数据。它们的返回值是成功读取或写入的记录数。[1][3]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值