读文件fread的问题
fread -从打开的fd中读取数据,并且是有缓存
man page
#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
坑:
- fread 不一定返回你想读的长度, 即返回值不一定等于
size * nmemb
, 即使还没有eof。所以你要判断判断返回值 - size 应该等于 1, 什么原因忘了,之前被坑过
while ((bytes = fread (data, 1, 1024, inFile)) != 0)
MD5_Update (&mdContext, data, 1024);
这样就完蛋了
while ((bytes = fread (data, 1, 1024, inFile)) != 0)
MD5_Update (&mdContext, data, bytes);
至于fread 和 read 的区别
总所周知的read 是系统调用,没有缓存的,而fread 是glibc提供的方法,以及 fread 会调用 read,但具体区别呢
以下glibc 的源码
_IO_size_t
_IO_fread (void *buf, _IO_size_t size, _IO_size_t count, _IO_FILE *fp)
{
_IO_size_t bytes_requested = size * count;
_IO_size_t bytes_read;
CHECK_FILE (fp, 0);
if (bytes_requested == 0)
return 0;
_IO_acquire_lock (fp);
bytes_read = _IO_sgetn (fp, (char *) buf, bytes_requested);
_IO_release_lock (fp);
return bytes_requested == bytes_read ? count : bytes_read / size;
}
libc_hidden_def (_IO_fread)
#ifdef weak_alias
weak_alias (_IO_fread, fread)
# ifndef _IO_MTSAFE_IO
strong_alias (_IO_fread, __fread_unlocked)
libc_hidden_def (__fread_unlocked)
weak_alias (_IO_fread, fread_unlocked)
# endif
#endif
使用strace 分析
void c_read() {
const uint64_t MAXDATABUFF = 1024;
FILE *f = fopen("dfs.s","rb");
unsigned char data[MAXDATABUFF] = {0};
int bytes;
while ((bytes = fread (data, 1, 1024, f)) != 0){}
fclose(f);
}
void os_read() {
const uint64_t MAXDATABUFF = 1024;
int fd = open("dfs.s",O_RDONLY);
unsigned char data[MAXDATABUFF] = {0};
int bytes;
while ((bytes = read (fd, data, 1024)) != 0){}
close(fd);
}
int main(){
c_read();
}
对比两种方式编译时 -o0 禁止优化
read
brk(0x55ffa6698000) = 0x55ffa6698000
openat(AT_FDCWD, "dfs.s", O_RDONLY) = 3
read(3, "mmap(0x7f45e1822000, 307200, PRO"..., 1024) = 1024
read(3, "0x56272ef19000\nopenat(AT_FDCWD, "..., 1024) = 1024
read(3, "NLY|O_CLOEXEC) = 3\nread(3, \"\\177"..., 1024) = 1024
read(3, "329272, ...}) = 0\nmmap(NULL, 133"..., 1024) = 1024
read(3, "AD|PROT_WRITE, MAP_PRIVATE|MAP_F"..., 1024) = 1024
read(3, "x7f31e0e78000, 1359872, PROT_REA"..., 1024) = 1024
read(3, " = 0\nbrk(NULL) "..., 1024) = 381
read(3, "", 1024) = 0
close(3) = 0
exit_group(0) = ?
fread
openat(AT_FDCWD, "dfs.s", O_RDONLY) = 3
fstat(3, {st_mode=S_IFREG|0644, st_size=6525, ...}) = 0
read(3, "mmap(0x7f45e1822000, 307200, PRO"..., 4096) = 4096
read(3, "AD|PROT_WRITE, MAP_PRIVATE|MAP_F"..., 4096) = 2429
read(3, "", 4096) = 0
exit_group(0) = ?
对比可见, fread 合并多次调用read
总结
fread 需要检查返回值