Posix电话'阅读'不读取整个文件

时间:2014-04-06 14:47:58

标签: c file io posix

在使用文件编程时,我偶然发现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'不会读取整个文件吗?

EDIT2:对不起,我正在使用带有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("%d\n", len);
    }
    close(id);

    println("--------");

    // loop 2
    FILE* fp = fopen("file.ext", "rb");
    while((len = fread(buf, 1, 1024, fp)) > 0) {
        printf("%d\n", len);
    }
    fclose(fp);

    while(1) {}

    return 0;
}

输出:

1024
331
--------
1024
1024
1024
1024
1024
1024
1024
1024
1024
1024
981

2 个答案:

答案 0 :(得分:2)

问题已更新......

fread()循环很奇怪:

while ((len = fread(buf, 1, 1024, fp) > 0))
    println(len);

看看括号 - 它们相当于:

while ((len =   (fread(buf, 1, 1024, fp) > 0)   ))

现在,fread()将返回读取的字节数,但分配给len的值将为01,因此从{{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("%d\n", 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: %d\n", (int)sb.st_size);
    return 0;
}

答案 1 :(得分:2)

您在文本模式下第一次打开文件,第二次以二进制模式打开文件。您需要在二进制模式下打开它两次。如果它不是二进制模式,则第一个control-z(十六进制值1A)表示&#34;文件结束&#34;。

添加以下内容(摆脱<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 world\r\n");
  fputc(0x1A, f);
  fprintf(f, "goodbye universe\r\n");
  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;
}

以上只打印&#34; hello world&#34;而不是&#34;再见宇宙&#34;。