Thread: Binary files I/O

  1. #1
    Registered User
    Join Date
    Jun 2010
    Posts
    182

    Binary files I/O

    Hi everybody.

    I'm thinking about a feasible solution for a simple task.
    I've a binary file 4,000 bytes big, and I need to add a space
    after each single byte writing an output binary file 8,000 bytes
    big.
    I've checked the manuals about files management, and a couple
    of solutions seems viable:

    1] read each single byte from input file with ch = fgetc(in)
    and write it to the output file with fputc(ch, out) followed by
    a fputc(space,out).

    2] read the whole 4,000 bytes into an array, manipulate it and write
    it to the output file with a single fwrite().

    The first solution looks pretty simple but awful because of the 4,000
    fgetc()
    that are apparently unnecessary for a simple task like this.

    The second solution appears more "mature" and require only a little
    bit more work on the array before writing it.

    How would you do that? would you choose solution 1 or 2? Or you have
    a totally different approach?

    Thanks

  2. #2
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by frktons View Post
    The first solution looks pretty simple but awful because of the 4,000
    fgetc()
    that are apparently unnecessary for a simple task like this.
    Look at it another way. Loading the whole file into memory just to do an operation that could be accomplished with single-character reads seems unnecessary for a simple task like this. Why would you want to deal with all of the data shuffling?

    I think the second solution is awful and doesn't scale. The first solution is what would immediately come to my mind, at least. Don't worry about lots of calls to fgetc(). The stdio library is designed to work efficiently in precisely this situation.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  3. #3
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,613
    My advice is to use fread and fwrite to read/write one byte at a time. I just don't like dealing with the issue whether char is signed or unsigned, and when your doing even trivial work in binary, unsigned values are easiest to work with. fread and fwrite is the way to do it. I'm sure fgetc and fputc can work, but you might have to compile with --unsigned-char or whatever it is.

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Honestly, it doesn't matter. fgetc and fputc return and take ints. Then they just peel off the first byte and use it. It doesn't matter if your character is signed or not.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by quzah View Post
    Honestly, it doesn't matter. fgetc and fputc return and take ints. Then they just peel off the first byte and use it. It doesn't matter if your character is signed or not.


    Quzah.
    I think you are right, according to my compiler documentation:
    fgetc function

    Purpose:
    Reads a character from a stream.

    Syntax:
    int fgetc(FILE *stream);

    Declared in:
    <stdio.h>

    Description:
    If the end-of-file indicator for the input stream pointed to by stream is not set and a next character is present, the fgetc function obtains that character as an unsigned char converted to an int and advances the associated file position indicator for the stream.


    Returns:
    If the end-of-file indicator for the stream is set, or if the stream is at end-of-file, the end-of-file indicator for the stream is set and the fgetc function returns EOF. Otherwise, the fgetc function returns the next character from the input stream. If a read error occurs, the error indicator for the stream is set and the fgetc function returns EOF. An end-of-file and a read error can be distinguished by use of the feof and ferror functions.
    Last edited by frktons; 07-21-2010 at 02:51 PM.

  6. #6
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Back to my pc for a while I coded the addspace program to read
    a binary file and write a spaced binary file.
    Code:
    //------------------------------------------------------------------------------------
    // addspace1.c
    //------------------------------------------------------------------------------------
    // File input: myfile.bin
    // File output: myfiles.bin
    //------------------------------------------------------------------------------------
    // Author: frktons @cProgramming forum
    // Date: 23 july 2010
    //------------------------------------------------------------------------------------
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void){
    
       int a_byte;
       int a_space = 32;
     
       FILE *fp_out;
       FILE *fp_in;
    
       char *file_name_in = "myfile.bin";
       char *file_name_out = "myfiles.bin";
       int ret_stat = 0;
    
       printf(" Creating file %s\n",file_name_out);
     
       fp_out = fopen(file_name_out, "wb");
    
       if (fp_out == NULL) {
          perror("\n Error opening output file");
          exit(EXIT_FAILURE); 
       }
    
       fp_in = fopen(file_name_in, "rb");
    
       if (fp_in == NULL) {
          perror("\n Error opening input file");
          exit(EXIT_FAILURE); 
       }
    
       while ((a_byte = fgetc(fp_in)) != EOF){
            fputc(a_byte,fp_out);
            fputc(a_space,fp_out);
       }
    
       fclose(fp_in);
       fclose(fp_out);
    
       printf("\n File %s created successfully\n",file_name_out);
       getchar();
       return 0;
    }
    This is the first version, others are going to arrive as I get time enough.

    Attached the file to perform the conversion, in case you want to try it.
    Put it in the same folder as the executable, and change the extension
    from txt to bin.

  7. #7
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    I like the 2nd option, personally. I don't like to rely on fgetc() and fputc() being buffered intelligently on all systems.

    If you like option 1 though, how about a small improvement. A small 2-character buffer whose 1st byte is from a fgetc() while the 2nd element always a space. Then you write 2 bytes at a time to the destination using fwrite(). Half the number of physical writes.

  8. #8
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Quote Originally Posted by nonoob View Post
    I like the 2nd option, personally. I don't like to rely on fgetc() and fputc() being buffered intelligently on all systems.

    If you like option 1 though, how about a small improvement. A small 2-character buffer whose 1st byte is from a fgetc() while the 2nd element always a space. Then you write 2 bytes at a time to the destination using fwrite(). Half the number of physical writes.
    As I said before, I like 2nd option too. Just for didactical purposes I'm
    doing this version also. Two or three more will follow, with some improvements
    Your idea is good,although we are not talking about physical writes because
    everything gets buffered by the system anyway.

  9. #9
    Registered User
    Join Date
    Jun 2010
    Posts
    182
    Here we have the 2nd version, a little bit more "advanced"
    Code:
    //------------------------------------------------------------------------------------
    // addspace2.c
    // File input: myfile.txt - 4000 bytes type binary
    // File output: myfiles.txt - 8000 bytes type binary
    //------------------------------------------------------------------------------------
    // Author: frktons @cProgramming forum
    // Date: 25 july 2010
    //------------------------------------------------------------------------------------
    
    #include <stdio.h>
    #include <stdlib.h>
    
    int main(void){
    
    //------------------------------------------------------------------------------------
    // Array for storing input data
    //------------------------------------------------------------------------------------
       char source[4000];
       char *ptr_source = source;
       char *source_start = ptr_source;
       char *source_limit = ptr_source + 3999; 
    //------------------------------------------------------------------------------------
    // Array for preparing output data
    //------------------------------------------------------------------------------------
       char target[8000];
       char *ptr_target = target;
       char *target_start = ptr_target;
       char *target_limit = ptr_target + 7999; 
    
       char a_space = ' ';
     
       FILE *fp_out;
       FILE *fp_in;
    
       char *file_name_in = "myfile.txt";
       char *file_name_out = "myfiles.txt";
       int ret_stat = 0;
    
    //------------------------------------------------------------------------------------
    // Array for output gets initialized with a_space
    //------------------------------------------------------------------------------------
       for (ptr_target = target_start; ptr_target <= target_limit; ptr_target++)
           *ptr_target = a_space;
    
       printf(" Reading file %s\n",file_name_in);
       printf(" Creating file %s\n",file_name_out);
     
       fp_in = fopen(file_name_in, "rb");
    
       if (fp_in == NULL) {
          perror("\n Error opening input file");
          exit(EXIT_FAILURE); 
       }
    
       ret_stat = fread(source,1,4000,fp_in);
    
       if (ret_stat != 4000) {
          perror("\n Error reading input file");
          exit(EXIT_FAILURE); 
       }
       
       ret_stat = fclose(fp_in);
    
       if (ret_stat != 0) {
          perror("\n Error closing input file");
          exit(EXIT_FAILURE); 
       }
    
    //------------------------------------------------------------------------------------
    // Array for output gets data from input array
    //------------------------------------------------------------------------------------
       for (ptr_target = target; ptr_target < target_limit; ptr_target +=2, ptr_source++)
           *ptr_target = *ptr_source;
    
       fp_out = fopen(file_name_out, "wb");
    
       if (fp_out == NULL) {
          perror("\n Error opening output file");
          exit(EXIT_FAILURE); 
       }
    
       ret_stat = fwrite(target,1,8000,fp_out);
    
       if (ret_stat != 8000) {
          perror("\n Error writing output file");
          exit(EXIT_FAILURE); 
       }
    
       ret_stat = fclose(fp_out);
    
       if (ret_stat != 0) {
          perror("\n Error closing output file");
          exit(EXIT_FAILURE); 
       }
       printf("\n File %s created successfully\n",file_name_out);
       getchar();
       return 0;
    }
    If you want to give it a try, use the file I posted in this thread and put
    executable and file in the same folder.
    Working on the real stuff, this was just to try some instructions.

    Enjoy.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Copying Binary Files
    By mikeman118 in forum C++ Programming
    Replies: 9
    Last Post: 08-11-2007, 10:55 PM
  2. Processing binary or plaintext files
    By Jags in forum C Programming
    Replies: 12
    Last Post: 08-04-2006, 02:35 PM
  3. Problem with Binary File I/O
    By DirX in forum C++ Programming
    Replies: 4
    Last Post: 03-01-2004, 09:34 AM
  4. fstream binary files
    By wesdgreat in forum C++ Programming
    Replies: 1
    Last Post: 01-29-2003, 10:12 PM
  5. Overlapped I/O and Completion Port :: Winsock
    By kuphryn in forum Windows Programming
    Replies: 0
    Last Post: 10-30-2002, 05:14 PM