fread的效率问题,不知讨论这个是否有意义

Sniper167 2008-08-09 10:12:48
size_t fread( void *buffer, size_t size, size_t count, FILE *stream );

比如读去一个比较大的文件,大小为filesize

fread(buffer, filesize, 1, fp);

fread(buffer, 1, filesize, fp);

上面两种用法,用哪种速度会快点呢?还是完全一样?
我个人倾向与第一种
...全文
719 8 打赏 收藏 转发到动态 举报
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
ForestDB 2008-08-18
  • 打赏
  • 举报
回复
从语义上来说,当然倾向第一种写法,读了1个元素,元素大小为filesize.
ForestDB 2008-08-18
  • 打赏
  • 举报
回复

count = total = elementSize * num;
while (count != 0) {
// read and decrease count
}

坏的代码简化下就是这样,count的计算使得两种写法没差.
mhyx_2008 2008-08-18
  • 打赏
  • 举报
回复
我认为两种写法的效率第一种应该略高些,因为这个函数要对正确读入的数据个数进行统计,但对空间的利用是一样的.

举个例子:
对于一个这样的结构体student:

struct student
{
int num;
char name;
int age;
};
如果在一个文件中记录了3个这样的结构体信息,后边又跟了一个字符串"hello world",然后是文件结束符.
count1=fread(buf,sizeof(struct student),5,fp);
count2=fread(buf,sizeof(struct student)*5,1,fp);

我们在用这两种方法去读的时候,都是只能够正确读取3个这样的结构体,
读取第四个都失败了(不过"hello world"还是被填充到第四个结构体中去了).
不过两种方法的返回值就不一样了:
count1=3;//在读的过程中需要对某段内存进行3次+1的动作,以记录并返回正确读入的个数.
count2=0;//在读的过程中需要对某段内存进行0次+1的动作,以记录并返回正确读入的个数.
所以fread(buf,sizeof(struct student)*5,1,fp);这种方法要稍微快一点,但是从硬盘提交数据到内存的速度都是一样的.
guzhilei1986 2008-08-18
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 wind_breez 的回复:]
个人感觉是时间与空间的取舍.根据自己情况的看。如果文件真的很大,那最好不要一次性读入内存。
[/Quote]
是不是就是有这样的一个规律,时间和空间永远是不能兼得的。
那空间大了时间就一定小吗?
空间小了,时间就一定大吗?
  • 打赏
  • 举报
回复
坏同学!~你整得太夸张了!~看不明白!~
wind_breez 2008-08-18
  • 打赏
  • 举报
回复
个人感觉是时间与空间的取舍.根据自己情况的看。如果文件真的很大,那最好不要一次性读入内存。
  • 打赏
  • 举报
回复
VS2005下效率一样
这是代码
#include <cruntime.h>
#include <stdio.h>
#include <mtdll.h>
#include <io.h>
#include <string.h>
#include <limits.h>
#include <internal.h>
#include <file2.h>
#include <dbgint.h>



#ifdef _DEBUG
#define _BUFFER_FILL_PATTERN _SECURECRT_FILL_BUFFER_PATTERN
#else /* _DEBUG */
#define _BUFFER_FILL_PATTERN 0
#endif /* _DEBUG */

/* define locking/unlocking version */
size_t __cdecl fread_s(
void *buffer,
size_t bufferSize,
size_t elementSize,
size_t count,
FILE *stream
)
{
size_t retval = 0;

if (elementSize == 0 || count == 0)
{
return 0;
}

/* validation */
_VALIDATE_RETURN((buffer != NULL), EINVAL, 0);
if (stream == NULL || count > (SIZE_MAX / elementSize))
{
if (bufferSize != SIZE_MAX)
{
memset(buffer, _BUFFER_FILL_PATTERN, bufferSize);
}

_VALIDATE_RETURN((stream != NULL), EINVAL, 0);
_VALIDATE_RETURN(count <= (SIZE_MAX / elementSize), EINVAL, 0);
}

_lock_str(stream);
__try
{
/* do the read; _fread_nolock_s will make sure we do not buffer overrun */
retval = _fread_nolock_s(buffer, bufferSize, elementSize, count, stream);
}
__finally
{
_unlock_str(stream);
}

return retval;
}

/* define the normal version */
size_t __cdecl _fread_nolock_s(
void *buffer,
size_t bufferSize,
size_t elementSize,
size_t num,
FILE *stream
)
{
char *data; /* point inside the destination buffer to where we need to copy the read chars */
size_t dataSize; /* space left in the destionation buffer (in bytes) */
size_t total; /* total bytes to read */
size_t count; /* num bytes left to read */
unsigned streambufsize; /* size of stream buffer */
unsigned nbytes; /* how much to read now */
unsigned nread; /* how much we did read */
int c; /* a temp char */

/* initialize local vars */
data = buffer;
dataSize = bufferSize;

if (elementSize == 0 || num == 0)
{
return 0;
}


count = total = elementSize * num;

if (anybuf(stream))
{
/* already has buffer, use its size */
streambufsize = stream->_bufsiz;
}
else
{
/* assume will get _INTERNAL_BUFSIZ buffer */
streambufsize = _INTERNAL_BUFSIZ;
}

/* here is the main loop -- we go through here until we're done */
while (count != 0) {
/* if the buffer exists and has characters, copy them to user
buffer */
if (anybuf(stream) && stream->_cnt != 0)
{
if(stream->_cnt < 0)
{
_ASSERTE(("Inconsistent Stream Count. Flush between consecutive read and write", stream->_cnt >= 0));
stream->_flag |= _IOERR;
return (total - count) / elementSize;
}

/* how much do we want? */
nbytes = (count < (size_t)stream->_cnt) ? (unsigned)count : stream->_cnt;
if (nbytes > dataSize)
{
if (bufferSize != SIZE_MAX)
{
memset(buffer, _BUFFER_FILL_PATTERN, bufferSize);
}
_VALIDATE_RETURN(("buffer too small", 0), ERANGE, 0)
}
memcpy_s(data, dataSize, stream->_ptr, nbytes);

/* update stream and amt of data read */
count -= nbytes;
stream->_cnt -= nbytes;
stream->_ptr += nbytes;
data += nbytes;
dataSize -= nbytes;
}
else if (count >= streambufsize)
{
/* If we have more than streambufsize chars to read, get data
by calling read with an integral number of bufsiz
blocks. Note that if the stream is text mode, read
will return less chars than we ordered. */

/* calc chars to read -- (count/streambufsize) * streambufsize */
nbytes = ( streambufsize ? (unsigned)(count - count % streambufsize) :
(unsigned)count );
if (nbytes > dataSize)
{
if (bufferSize != SIZE_MAX)
{
memset(buffer, _BUFFER_FILL_PATTERN, bufferSize);
}
_VALIDATE_RETURN(("buffer too small", 0), ERANGE, 0)
}

nread = _read(_fileno(stream), data, nbytes);
if (nread == 0) {
/* end of file -- out of here */
stream->_flag |= _IOEOF;
return (total - count) / elementSize;
}
else if (nread == (unsigned)-1) {
/* error -- out of here */
stream->_flag |= _IOERR;
return (total - count) / elementSize;
}

/* update count and data to reflect read */
count -= nread;
data += nread;
dataSize -= nread;
}
else
{
/* less than streambufsize chars to read, so call _filbuf to
fill buffer */
if ((c = _filbuf(stream)) == EOF) {
/* error or eof, stream flags set by _filbuf */
return (total - count) / elementSize;
}

/* _filbuf returned a char -- store it */
if (dataSize == 0)
{
if (bufferSize != SIZE_MAX)
{
memset(buffer, _BUFFER_FILL_PATTERN, bufferSize);
}
_VALIDATE_RETURN(("buffer too small", 0), ERANGE, 0)
}
*data++ = (char) c;
--count;
--dataSize;

/* update buffer size */
streambufsize = stream->_bufsiz;
}
}

/* we finished successfully, so just return num */
return num;
}

size_t __cdecl fread(
void *buffer,
size_t elementSize,
size_t count,
FILE *stream
)
{
/* assumes there is enough space in the destination buffer */
return fread_s(buffer, SIZE_MAX, elementSize, count, stream);
}

size_t __cdecl _fread_nolock(
void *buffer,
size_t elementSize,
size_t count,
FILE *stream
)
{
/* assumes there is enough space in the destination buffer */
return _fread_nolock_s(buffer, SIZE_MAX, elementSize, count, stream);
}
K行天下 2008-08-09
  • 打赏
  • 举报
回复
应该是前面的快,但是觉得缓冲区不应该太大,可以分为几次读取

69,336

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧