0

I've been trying to copy 2 binary files one to the other using fread and write. I've read a couple of articles that explain how they work but I don't understand what is my mistake here.

I've tried switching the char fread is used on to an int so the -1 wont interfere with the process but it didn't seem to work.

Some links I looked up to search for an answer:

Why is “while (!feof(file))” always wrong?
https://www.tutorialspoint.com/c_standard_library/c_function_fwrite.htm
https://www.tutorialspoint.com/c_standard_library/c_function_fread.htm
Copying Binary Files
Copying data from one text file to another in C

while (tempNum != EOF) {
    fread(tempNum, 1, 1, fptr);
    fwrite(tempNum, 1, 1, fp);
}

Example for you to test:

#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
FILE *fptr;
FILE *fp;

int main(int argc, char** argv)
{
    int flag = 0;
    int exist = 0;
    char currentChar = 0;
    int tempNum = 0;
    fptr = 0;
    fp = fopen(*(argv + 3), "r");
    fptr = fopen(*(argv + 2), "r");
    char temp_array[10000] = { 0 };

    if (fptr == NULL)
    {
        printf("we cannot extract from nothing.");
        flag++;
    }
    else if (fp != NULL)
    {
        printf("This file already exists. If you would like to overwrite it enter 0. %s");
        scanf("%d", &flag);
    }

    if (!strcmp(*(argv + 1), "textCopy") && flag == 0)
    {
        fclose(fp);
        fclose(fptr);
        printf("A");
        fp = fopen(*(argv + 3), "w");
        fptr = fopen(*(argv + 2), "r");
        printf("%s , %s", *(argv + 2), *(argv + 3));

        while (currentChar != EOF)
        {
            printf("a");
            currentChar = fgetc(fptr);
            fputc(currentChar, fp);
        }

        fclose(fp);
        fclose(fptr);
    }
    else if (!strcmp(*(argv + 1), "binaryCopy") && flag == 0)
    {
        printf("A");
        fptr = fopen(*(argv + 2), "r");
        fp = fopen(*(argv + 3), "w");

        while (tempNum != EOF)
        {
            fread(tempNum, 1, 1, fptr);
            fwrite(tempNum, 1, 1, fp);
        }
    }

    getchar();
    getchar();
    return 0;
}

Expected: to get 2 identical files.

Actual: I successfully copy the first 6 bytes of the file (I used hex workshop) but afterwards Visual Studio crashed and said that the parameters passed to the function fread consider the input fatal.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ron zamir
  • 23
  • 6
  • Check the result of the functions instead. – Lundin May 07 '19 at 15:10
  • 1
    @Lundin what do you mean by the results of it? the return value? – ron zamir May 07 '19 at 15:12
  • Unsure whether a true duplicate but fix this and everything should work: [Why is “while (!feof(file))” always wrong?](https://stackoverflow.com/q/5431941/3545273) – Serge Ballesta May 07 '19 at 15:12
  • 1
    Check the result of `fread` first. If it has returned a value other than the expected number of elements (`1` in your case) you can check `feof(fptr)` or `ferror(fptr)` afterwards. – Bodo May 07 '19 at 15:15
  • Yes the return value. These return the number of bytes written/read. If not the expected, then there was a problem, likely EOF. – Lundin May 07 '19 at 15:15
  • @Bodo but the problem isn't this. ive tried setting up that counter = fread.... and then check if counter is equal to 1 before proceding forward, but i constantly get an error after the first 6 bytes. idk why. – ron zamir May 07 '19 at 15:20
  • 2
    This cannot even possibly compile without warnings. – Antti Haapala -- Слава Україні May 07 '19 at 15:23
  • @ronzamir Please add a [mcve], i.e. enough code that allows someone to compile and test your program. We don't know how `tempNum` gets set, and in your example `tempNum` will never change. Also show **in your question** the contents of the input file. You should [edit] your question to add the missing information. Links to the "a couple of articles" might also be interesting. – Bodo May 07 '19 at 15:25
  • @Bodo done, ive added everything, thank you! – ron zamir May 07 '19 at 15:31

2 Answers2

1

First, I try to minimize your program. I assume you want to execute the path for copying binary data. I remove the unrelated stuff and use hard coded input and output files for simplicity.

(There are some unrelated errors in the original code not mentioned here.)

#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>
FILE *fptr;
FILE *fp;
int main(int argc, char** argv)
{
    int tempNum = 0;
    char temp_array[10000] = { 0 };

    fptr = fopen("input.txt", "r");
    /* TODO: handle possible error */
    fp = fopen("output.txt", "w");
    /* TODO: handle possible error */

    /* FIXME: This is not the correct way to check for EOF. */
    while (tempNum != EOF)
    {
        /* FIXME: The first argument must be a buffer for reading the data. You should check the return code. */
        fread(tempNum, 1, 1, fptr);
        /* FIXME: The first argument must be a buffer containing the data. You should check the return code. */
        fwrite(tempNum, 1, 1, fp);
    }
    /* TODO: close files */
    return 0;
}

And now a modified version that works and handles some errors.

#include <string.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/stat.h>

FILE *fptr = NULL;
FILE *fp = NULL;
int main(int argc, char** argv)
{
    int tempNum = 0;
    char temp_array[10000] = { 0 };

    fptr = fopen("input.txt", "r");
    if(fptr == NULL) /* handle possible error */
    {
        perror("fopen(input.txt)");
        return 1;
    }
    fp = fopen("output.txt", "w");
    if(fp == NULL) /* handle possible error */
    {
        perror("fopen(output.txt)");
        fclose(fptr);
        return 1;
    }

    do
    {
        tempNum = fread(temp_array, 1, 1, fptr);
        if(tempNum > 0)
        {
            if(fwrite(temp_array, 1, tempNum, fp) != tempNum)
            {
                perror("fwrite");
                fclose(fptr);
                fclose(fp);
                return 1;
            }
        }
    }
    while(tempNum > 0);

    /* after fread() returned less than we expected, check for error */
    if(ferror(fptr))
    {
        perror("fread");
        fclose(fptr);
        fclose(fp);
        return 1;
    }

    /* When we reach this point we can assume the loop ended on EOF */
    fclose(fptr);
    fclose(fp);
    return 0;
}
Bodo
  • 9,287
  • 1
  • 13
  • 29
0

This is a task I encounter so frequently that I have a skeleton code snippet for it:

typedef unsigned char byte;

byte *buffer = NULL;
size_t len;

fseek(input_file, 0, SEEK_END);
len = ftell(input_file);
rewind(input_file);

buffer = malloc(len + 1);
if(NULL == buffer)
{
    // handle malloc failure
}

fread(buffer, 1, len, input_file);  
fclose(input_file);

fwrite(buffer, 1, len, output_file);
fclose(output_file);

free(buffer);
buffer = NULL;

Note that if your file is too large malloc may fail and the best solution is buffering chunks of the file at a time in a loop.

Govind Parmar
  • 20,656
  • 7
  • 53
  • 85