Home > front end >  fread and fwrite result file size are different
fread and fwrite result file size are different

Time:08-05

I am writing a program in Visual Studio. I copied a file using fread and fwrite. The output file size is bigger then input file. Can you explain the reason?

#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);
}

CodePudding user response:

You open the files in text mode, which on the Windows operating system using Visual Studio involves non trivial translation phases, including end of line conversion. If your files have binary contents, such as executable, image and document files, end of line conversion replaces '\n' bytes with CR LF pairs, thereby increasing the output size.

You can avoid this issue by opening the files in binary mode with "rb" and "wb" mode strings.

Also note that a stream must be open in binary mode for ftell() to reliably return the file size, assuming the file supports seeking and is not larger than LONG_MAX which is only 2GB on Windows. Using stat to retrieve the file size from the OS is a better approach for POSIX systems. Copying the file one block at a time is also more reliable: it works for streams that do not support seeking and allows for copying files larger than available memory.

Here is a modified version with error checking:

#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;
}
  • Related