Can i use fgetc() or fputc() in a binary file?
Asked Answered
E

2

6

I am creating an archive program in C, and i want it to save files i provide, list and extract them.
I had many issues because i used a text file for saving, and it is not the best choice if i want to process binary files like music or photos, because when i extract them, they are not executed correctly (they are corrupted). In order to solve this problem, i wanted to create a binary archive file.

Code for file writing (on extraction) is the following:

void scriviFile(const char * arrivo)                                //scrive i file creati in precedenza
{
    FILE * partenza;
    FILE * target;
    int c;
    int spazio = 'a';
    int i = 0;
    int pos;
    char * path;
    path = collegaSlash(getcwd(NULL, 0), nome);
    partenza = fopen(path, "rb");
    fseek(partenza, inizio, SEEK_SET);
    target = fopen(arrivo, "wb");                                           //apro il file
    if (target) {                                                               //se è aperto
        while ((c = fgetc(partenza)) != EOF && ftell(partenza)<=fine-10) {                                  //e il carattere preso non eccede la fine del file
            fputc(c, target);
            fputc(c, stdout);
            pos = ftell(partenza);
            if(pos==fine)
            {
                break;
            }
                                                                            //scrivo lo stesso carattere in out (file in uscita)
        }                                                                   //

        fclose(target);                                                     //chiudo il file
        fclose(partenza);
    } 
    else 
    {
        printf("errore di scrittura del file \n");
    }

}

Since i need binary files to be extracted correctly, can i use code i wrote above, or do i have to change all fgetc() and fputc() functions with fread() and fwrite()?

Thanks

Enface answered 10/5, 2013 at 9:23 Comment(6)
yes, you should change, or you might spend a considerable time with debugger to discover that your fget got some invalid value and created havocSubstratosphere
Either there is no problem when performing read write one letter to open a binary file.Poleyn
@Substratosphere What on Earth are you talking about? I see no problem with the use of fgetc here. Stop misdiagnosing. I do see usage of several variables which aren't declared. For this reason, we can't help AndreaGottardi with this code. AndreaGottardi: Create a minimal, compilable testcase to write the information from a structure (which isn't necessarily a struct) to a file. Then create a minimal, compilable testcase to read the information back from the file into a structure. Provide both of them here, but ONLY if they actually compile... Ask a question about something you don't understand...Heinous
Those who use the fgetpos(fsetpos) than ftell(fseek) might be better in the case of dealing with large files.Poleyn
@undefinedbehaviour I know it doesn't compile, it's not the entire program. It was only an example function for better explaining. I asked on StackOverflow why this program didn't extract files, and someone answered me saying it's a problem regarding binary files and text files.Enface
@undefinedbehaviour, yes, my mistake, i should have written in context to the program.Substratosphere
O
13

You're using fgetc() and fputc() as you can see from the man page descriptions these function:

fgetc() reads the next character from stream and returns it as an unsigned char cast to an int, or EOF on end of file or error.

fputc() writes the character c, cast to an unsigned char, to stream.

A character, in C, is defined by the standard to always be exactly 1 byte (8 bits), this means when you use fxxxc() on a file you'll get 1 byte (that just happens to be a character in a text file).

If you extract and rebuild a binary file, byte by byte, you'll get an exact duplicate. So no, there is no issues with using fgetc() and fputc() on a binary file type. You can always prove this to yourself with a simple example program... for example:

int main()
{
    FILE * fptr = fopen("small_pic.jpg", "rb");  // open existing binary picture
    char buffer[10000] = {0}; // the pic is 6kb or so, so 10k bytes will hold it
    FILE * fptr2 = fopen("new_small_pic.jpg", "wb"); // open a new binary file 
                                                       // for our copy of the pic
    unsigned long fileLen;
    unsigned long counter;

    fseek(fptr, 0, SEEK_END);
    fileLen=ftell(fptr);      // get the exact size of the pic
    fseek(fptr, 0, SEEK_SET);

    for(counter=0; counter<fileLen; counter++)
        fputc(fgetc(fptr),fptr2);  // read each byte of the small_pic.jpg and make
                                           // a new pic from it

    fclose(fptr);
    fclose(fptr2);
return 0;
}

end result: we have two of the exact same images, because fgetc() and fputc() can be used on binary files.

Ouse answered 10/5, 2013 at 12:59 Comment(1)
Hey man great answer. Quick question: do the initialization brackets in your line with char buffer[10000] = {0}; initialize each element in the array to a value of 0?Cosmism
H
0

I am creating an archive program in C, and i want it to save files i provide, list and extract them. I had many issues because i used a text file for saving, and it is not the best choice if i want to process binary files like music or photos, because when i extract them, they are not executed correctly (they are corrupted). In order to solve this problem, i wanted to create a binary archive file.

--SNIP--

Since i need binary files to be extracted correctly, can i use code i wrote above, or do i have to change all fgetc() and fputc() functions with fread() and fwrite()?

You can use the code you wrote above when working in binary mode. It's got nothing to do with fgetc, fputc, fread and fwrite. The reason this function won't work particularly well when working in text mode is that ftell isn't guaranteed to useful for anything other than fseeking back to that location, hence the code ftell(partenza)<=fine-10 isn't particularly suitable when working with files open in text mode. By refactoring your code, you can remove ftell and work with files larger than 4GB as a result... but that shouldn't be the only reason to refactor this code.

Heinous answered 10/5, 2013 at 16:18 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.