在 C 中使用 fread 读取 pdf 文件并没有按预期结束

Reading a pdf file with fread in C does not end up as expected

我正在尝试从一个 pdf 文件读取并写入另一个文件,我 运行 遇到了问题。

while循环中,fread只读取了589字节,第一次预计是1024字节。 在第二个循环中,fread 读取 0 个字节。

我确定 pdf 文件超过 1024 字节。

Here is a similar problem。现象是一样的。但是我不使用导致该问题的 strlen()

那么我该如何解决这个问题呢?

我的代码在这里:

#include <stdio.h>

#define MAXLINE 1024

int main() {
    FILE *fp;
    int read_len;
    char buf2[MAXLINE];
    FILE *fp2;
    fp2 = fopen("test.pdf", "w");
    if ((fp = fopen("LearningSpark.pdf", "r")) == NULL) {
        printf("Open file failed\n");
    }
    while ((read_len = fread(buf2, sizeof(char), MAXLINE, fp)) > 0) {
        int write_length = fwrite(buf2, sizeof(char), read_len, fp2);
        if (write_length < read_len) {
            printf("File write failed\n");
            break;
        }
    }
    return 0;
}

fopen(filename, "r") 取决于系统。例如,如果您在 Windows 上,请参阅 this post 了解您读取的数据可能发生的情况。基本上它与某些字符在文本模式下在不同系统上的翻译方式有关,即\n是“End-of-Line" 在 Unix-type 系统上,但在 Windows 上是 \r\n

重要提示:在 Windows 上,ASCII 字符 27 将导致 End-Of-File,如果以文本模式阅读,"r",导致 fread() 过早终止。

要读取二进制文件,请使用 "rb" 说明符。同样对于"w",如所述,您应该使用"wb"来写入二进制数据。

二进制文件,例如 pdf 文件必须以二进制模式打开,以防止在遗留系统(例如 Windows 上进行行尾转换和其他文本模式处理。

另请注意,当 fopen() 失败时您应该中止并且您应该关闭文件。

这是修改后的版本:

#include <errno.h>
#include <stdio.h>
#include <string.h>

#define MAXLINE 1024

int main() {
    char buf2[MAXLINE];
    int read_len;
    FILE *fp;
    FILE *fp2;
    if ((fp = fopen("LearningSpark.pdf", "rb")) == NULL) {
        fprintf(stderr, "Open file failed for %s: %s\n", "LearningSpark.pdf", strerror(errno));
        return 1;
    }
    if ((fp2 = fopen("test.pdf", "wb")) == NULL) {
        fprintf(stderr, "Open file failed for %s: %s\n", "test.pdf", strerror(errno));
        fclose(fp);
        return 1;
    }

    while ((read_len = fread(buf2, 1, MAXLINE, fp)) > 0) {
        int write_length = fwrite(buf2, 1, read_len, fp2);
        if (write_length < read_len) {
            fprintf(stderr, "File write failed: %s\n", strerror(errno));
            break;
        }
    }
    fclose(fp);
    fclose(fp2);
    return 0;
}