在使用文件编程时,我偶然发现了C库"fread"函数和POSIX调用"read"之间的一些奇怪差异;"read"只读取文件的几个字节,而"fread"读取整个文件。此代码仅读取 1024 + 331 字节,然后"read"返回 0:
char buf[1024];
int id = open("file.ext", 0);
int len;
while((len = read(id, buf, 1024)) > 0)
println(len);
虽然此代码按预期读取整个文件,但大约 11kb:
char buf[1024];
FILE* fp = fopen("file.ext", "rb");
int len;
while((len = fread(buf, 1, 1024, fp)) > 0)
println(len);
你能说出为什么"read"不会读取整个文件吗?
编辑2:很抱歉,我正在使用带有MinGW的Windows,并读取二进制文件
编辑:一个完整的例子:
#include <io.h>
#include <stdio.h>
int main() {
char buf[1024];
int len;
// loop 1
int id = open("file.ext", 0);
while((len = read(id, buf, 1024)) > 0) {
printf("%dn", len);
}
close(id);
println("--------");
// loop 2
FILE* fp = fopen("file.ext", "rb");
while((len = fread(buf, 1, 1024, fp)) > 0) {
printf("%dn", len);
}
fclose(fp);
while(1) {}
return 0;
}
输出:
1024
331
--------
1024
1024
1024
1024
1024
1024
1024
1024
1024
1024
981
您第一次在文本模式下打开文件,第二次在二进制模式下打开文件。您需要在二进制模式下两次打开它。如果它不在二进制模式下,第一个 control-z(十六进制值 1A)表示"文件结束"。
添加以下内容包括(删除<io.h>
):
#include <unistd.h>
#include <fcntl.h>
调用打开方式如下:
int id = open("spiderman.torrent", O_RDONLY|O_BINARY);
下面是 control-z 结束文件的示例:
#include <stdio.h>
void writeit() {
FILE *f = fopen("test.txt", "wb");
fprintf(f, "hello worldrn");
fputc(0x1A, f);
fprintf(f, "goodbye universern");
fclose(f);
}
void readit() {
int c;
FILE *f = fopen("test.txt", "r");
while ((c = fgetc(f)) != EOF)
putchar(c);
fclose(f);
}
int main() {
writeit();
readit();
return 0;
}
以上只印"你好世界",不印"再见宇宙"。
问题已更新...
fread()
循环很奇怪:
while ((len = fread(buf, 1, 1024, fp) > 0))
println(len);
看看括号——它们相当于:
while ((len = (fread(buf, 1, 1024, fp) > 0) ))
现在,fread()
将返回读取的字节数,但分配给len
的值将是 0
或 1
,因此从println()
打印应重复1
几次,然后停止。
您是实际代码,还是在创建问题时输入错误?
编译并运行这个程序(我称之为rd
从rd.c
编译):
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#define FILENAME "file.ext"
static void println(int val)
{
printf("%dn", val);
}
int main(void)
{
char buf[1024];
int len;
int id = open(FILENAME, 0);
while ((len = read(id, buf, 1024)) > 0)
println(len);
close(id);
FILE *fp = fopen(FILENAME, "rb");
while ((len = fread(buf, 1, 1024, fp)) > 0)
println(len);
fclose(fp);
struct stat sb;
stat(FILENAME, &sb);
printf("Size: %dn", (int)sb.st_size);
return 0;
}
示例输出:
$ ls -l file.ext
-rw-r--r-- 1 jleffler staff 7305 Apr 6 08:08 file.ext
$ ./rd
1024
1024
1024
1024
1024
1024
1024
137
1024
1024
1024
1024
1024
1024
1024
137
Size: 7305
$