fread 和 fwrite 结果文件大小不同

Byu*_*ang 2 c filesize fwrite fread

我正在 Visual Studio 中编写程序。\n我使用fread和复制了一个文件fwrite。\n输出文件大小比输入文件大。\n你能解释一下原因吗?

\n
#define _CRT_SECURE_NO_WARNINGS\n#include <stdio.h>\n#include <stdlib.h>\n#include <memory.h>\n\nint main()\n{\n    char *buffer;\n    int fsize;\n\n    FILE *fp = fopen("test.txt", "r");\n    FILE *ofp = fopen("out.txt", "w");\n    fseek(fp, 0, SEEK_END);\n    fsize = ftell(fp);\n\n    buffer = (char *)malloc(fsize);\n    memset(buffer, 0, fsize); // buffer\xeb\xa5\xbc 0\xec\x9c\xbc\xeb\xa1\x9c \xec\xb4\x88\xea\xb8\xb0\xed\x99\x94\n\n    fseek(fp, 0, SEEK_SET);\n    fread(buffer, fsize, 1, fp);\n\n    fwrite(buffer, fsize, 1, ofp);\n\n    fclose(fp);\n    fclose(ofp);\n    free(buffer);\n}\n
Run Code Online (Sandbox Code Playgroud)\n

chq*_*lie 5

您以文本模式打开文件,在使用 Visual Studio 的 Windows 操作系统上,这涉及到重要的翻译阶段,包括行尾转换。如果您的文件具有二进制内容,例如可执行文件、图像和文档文件,则行尾转换会将“\n”字节替换为 CR LF 对,从而增加输出大小。

"rb"您可以通过使用和模式字符串以二进制模式打开文件来避免此问题"wb"

另请注意,流必须以二进制模式打开才能ftell()可靠地返回文件大小,假设文件支持查找并且不大于LONG_MAXWindows 上的 2GB。对于 POSIX 系统,使用stat从操作系统检索文件大小是更好的方法。一次复制一个文件块也更可靠:它适用于不支持查找的流,并允许复制大于可用内存的文件。

这是带有错误检查的修改版本:

#ifdef _MSC_VER
#define _CRT_SECURE_NO_WARNINGS
#endif

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

int main() {
    const char *inputfile = "test.txt";
    const char *outputfile = "out.txt";

    FILE *fp = fopen(inputfile, "rb");
    if (fp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", inputfile, strerror(errno);
        return 1;
    }

    FILE *ofp = fopen(outputfile, "wb");
    if (ofp == NULL) {
        fprintf(stderr, "cannot open %s: %s\n", outputfile, strerror(errno);
        return 1;
    }

    if (fseek(fp, 0, SEEK_END)) {
        fprintf(stderr, "%s: cannot seek to the end of file: %s\n",
                inputfile, strerror(errno);
        return 1;
    }
   
    size_t fsize = ftell(fp);

    char *buffer = calloc(fsize, 1);
    if (buffer == NULL) {
        fprintf(stderr, "cannot allocate %zu bytes: %s\n",
                fsize, strerror(errno);
        return 1;
    }

    rewind(fp);
    size_t nread = fread(buffer, fsize, 1, fp);
    if (nread != fsize) {
        fprintf(stderr, "%s: read %zu bytes, file size is %zu bytes\n".
                inputfile, nread, fsize);
    }

    size_t nwritten = fwrite(buffer, nread, 1, ofp);
    if (nwritten != nread) {
        fprintf(stderr, "%s: wrote %zu bytes, write size is %zu bytes\n".
                outputfile, nwritten, nread);
    }
    fclose(fp);
    if (fclose(ofp)) {
        fprintf(stderr, "%s: error closing file: %s\n".
                outputfile, strerror(errno));
    }
    free(buffer);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)