我正在用Visual Studio编写一个程序. 我用freadfwrite复制了一个文件. 输出文件大小大于输入文件大小. 你能解释一下原因吗?

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

int main()
{
    char *buffer;
    int fsize;

    FILE *fp = fopen("test.txt", "r");
    FILE *ofp = fopen("out.txt", "w");
    fseek(fp, 0, SEEK_END);
    fsize = ftell(fp);

    buffer = (char *)malloc(fsize);
    memset(buffer, 0, fsize); // buffer를 0으로 초기화

    fseek(fp, 0, SEEK_SET);
    fread(buffer, fsize, 1, fp);

    fwrite(buffer, fsize, 1, ofp);

    fclose(fp);
    fclose(ofp);
    free(buffer);
}

推荐答案

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

您可以通过以二进制模式打开包含"rb""wb"模式字符串的文件来避免此问题.

另请注意,假设文件支持查找且不大于LONG_MAX(在Windows上仅为2 GB),则流必须以二进制模式打开ftell()才能可靠地返回文件大小.对于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;
}

C++相关问答推荐

带双指针的2D数组

gcc已编译的可执行文件TSB是否同时暗示最低有效字节和最低有效位?

POSIX文件描述符位置

无效使用未定义类型'structsquare'?

在C中使用强制转换将uint16_t转换为uint8_t [2]是否有效?

在C中使用动态内存分配找到最小的负数

显式地将值转换为它从函数返回的类型的含义是什么?

使用额外的公共参数自定义printf

C是否用0填充多维数组的其余部分?

调用mProtection将堆栈上的内存设置为只读,直接导致程序SIGSEGV

一旦运行长度超过2,编译器是否会优化";strnlen(mystring,32)>;2";以停止循环?

为什么函数是按照定义的顺序执行的,而不是按照从avr-c中的int main()调用的顺序执行的?

C整型和_泛型.哪些类型是兼容的?

C程序向服务器发送TCPRST

STM32 FATFS用户手册(Um1721)中的代码正确吗?

Leet代码运行时错误:代码不会在Leet代码上编译,而是在其他编译器中编译,如netbeans和在线编译器

与指针的原始C数组或C++向量<;向量<;双>>;

C struct 中的冒泡排序

是什么阻止编译器优化手写的 memcmp()?

10 个字节对于这个 C 程序返回后跳行的能力有什么意义