[c] some doubts with fread and fwrite

This is a discussion on [c] some doubts with fread and fwrite within the C Programming forums, part of the General Programming Boards category; Code: #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]){ if(argc != 3){ printf("Usage: ./copy filename newfile\n"); exit(1); } int ...

  1. #1
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    52

    [c] some doubts with fread and fwrite

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int main(int argc, char *argv[]){
      
      if(argc != 3){
        printf("Usage: ./copy filename newfile\n");
        exit(1);
      }
      
      int bytes;
      long file_size, file_copied_size;
      FILE *file_to_copy, *new_file;
      
      if((file_to_copy = fopen(argv[1], "rb")) == NULL){
        printf("File cannot be opened - read\n");
        exit(1);
      }
      if((new_file = fopen(argv[2], "wb")) == NULL){
        printf("File cannot be opened - write\n");
        exit(1);
      }
    
    
      fseek(file_to_copy, 0, SEEK_END);
      file_size = ftell(file_to_copy);
      rewind(file_to_copy);
      
      char *buffer = malloc(1024 * 1024); /* Imposto un buffer di 1MB per maggiore efficienza */ 
      if(!buffer){
        printf("Errore allocazione memoria\n");
        fclose(file_to_copy);
        fclose(new_file);
        exit(1);
      }
      
       /* In questo modo copio file grandi 1MB alla volta cosė il trasferimento č pių veloce ed efficiente inoltre fread() ritorna 0 quando c'č un errore o quando incontra EOF */
      while (!feof(file_to_copy)){
        bytes = fread(buffer, 1, sizeof(buffer), file_to_copy); //controllare exit status
        fwrite(buffer, 1, bytes, new_file);
        if(ferror(new_file)){
          perror("Errore scrittura"); /* perror printa anche l'errore che ferror ha incontrato */
          fclose(file_to_copy);
          fclose(new_file);
          exit(1);
        }
      }
      
      fseek(new_file, 0, SEEK_END);
      file_copied_size = ftell(new_file);
      rewind(new_file);
      if(file_size != file_copied_size){
        printf("Il file %s non č stato copiato correttamente\n", argv[2]);
      }
      else{
        printf("File successfully copied :)\n");
      }  
      fclose(file_to_copy);
      fclose(new_file);
      free(buffer);
    
    
      return EXIT_SUCCESS;
    }
    I have some doubts:
    1) I have to check the return code of fread because - for example - if bytes become 0 due to an error, 0 will be written into the copied file.
    But my question is: how to do it? Because fread can return 0 but can also return a short value ....
    2) how can fread go throught the file? If i copy a 5MB file how can fread move from 1MB in 1MB without something that say to it "hey you have to put your offset 1MB after the 1MB you've just copied"?
    3) why not to clear the buffer after every use? I mean something like:
    Code:
    while (!feof(file_to_copy)){
            bytes = fread(buffer, 1, sizeof(buffer), file_to_copy);
            fwrite(buffer, 1, bytes, new_file);
            memset(buffer, 0, sizeof(buffer));
    }

  2. #2
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,750
    It's related to why it's a bad idea to control the loop with feof(). Read this: SourceForge.net: Feof - cpwiki

    You can do something like
    Code:
     while ((bytes = fread(buffer, sizeof(buffer), 1, file_to_copy)) ==1)
    When this breaks you are basically done, but you should then check feof() to see if the loop exited for that reason. If not, it implies failure to copy.
    Last edited by whiteflags; 06-16-2012 at 02:38 AM.

  3. #3
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    52
    But have i to write this:
    Code:
    fread(buffer, sizeof(buffer), 1, file_to_copy)
    or this:
    Code:
    fread(buffer, 1, sizeof(buffer), file_to_copy);
    what are the difference?

  4. #4
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,749
    Read the manual page for fread()

    > fread(buffer, sizeof(buffer), 1, file_to_copy)
    This will either read one whole buffer, or nothing.
    Unless your file is an integral multiple of sizeof(buffer), it will fail to read the remaining bytes at the end of the file.

    > fread(buffer, 1, sizeof(buffer), file_to_copy);
    This on the other hand will fill buffer with as many bytes as it can.
    When the end of the file is reached, the buffer will be partially filled, and the return result will tell you how many bytes were read.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  5. #5
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    52
    Yes, i've tried and the first didn't work
    However, about the buffer, why have i to not clean it after every use?

  6. #6
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,750
    >> Yes, i've tried and the first didn't work
    Sorry about flipping the arguments like that.

    >> However, about the buffer, why have i to not clean it after every use?
    Well there is really no sense in "cleaning", the same location will be reused regardless of what is stored previously. The only trouble you would have is remembering where to '\0'-terminate strings, in which case a zero'd out buffer would actually protect you if you are careful to leave one zero at the end, but usually strings are written to binary files such that their length is apparent from the data (either by storing the length first or some other scheme).

  7. #7
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    52
    Quote Originally Posted by whiteflags View Post
    >> Yes, i've tried and the first didn't work
    Well there is really no sense in "cleaning", the same location will be reused regardless of what is stored previously. The only trouble you would have is remembering where to '\0'-terminate strings, in which case a zero'd out buffer would actually protect you if you are careful to leave one zero at the end, but usually strings are written to binary files such that their length is apparent from the data (either by storing the length first or some other scheme).
    I try to explain to you my doubt in a better way if i have an array:
    Code:
    char array[1024]
    and i write 500 char into it i have 500 char occupied and 524 that are free right?
    If the next time i'll write into the array i write 100 char and print the array, 100 char will be printed but also the other 400 that in the previous step have been stored into the array because the array have not been cleaned. Right?
    So if i have a buffer and i wrote into it 1024 char and the next time i'll write into the buffer i write only 500 char there are other 524 char stored...isn't it??

  8. #8
    Registered User whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    7,750
    If the next time i'll write into the array i write 100 char and print the array, 100 char will be printed but also the other 400 that in the previous step have been stored into the array because the array have not been cleaned. Right?
    What about it? That's why fread has a return value, so that you can understand how many of a particular item, of a particular size, was stored. You are supposed to use that information to use the buffer correctly.

    I only mentioned strings in my last post because strings aren't properly '\0'-terminated in many binary files. Zeroing out your memory might be an approach to handling the problem, but I don't agree with that practice.

    Consider this program:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void writeMessage (const char *message, const char *file)
    {
        FILE *fp = fopen(file, "wb");
        size_t length = strlen(message);
        fwrite(&length, sizeof(length), 1, fp);
        fwrite(message, 1, length, fp);
        fclose(fp);
    }
    
    void readMessage (const char *file)
    {
        FILE *fp = fopen(file, "rb");
        size_t length = 0;
        char *message = NULL;
        printf("Reading file: %s\n", file);
        fread(&length, sizeof(length), 1, fp);
        if ( (message = malloc(length + 1)) != NULL ) {
            fread(message, 1, length, fp);
            message[length] = '\0';
            printf("message: >%s<\n", message);
            free(message);
        }
        fclose(fp);
    }
    
    int main()
    {
        writeMessage("Twilight mushrooms from the Moon.", "file.bin");
        readMessage("file.bin");
        return 0;
    }
    
    /* 
    Program output: 
    Reading file: file.bin
    message: >Twilight mushrooms from the Moon.<
    */
    Some methods of storage retrieval are easier to program than others.
    Last edited by whiteflags; 06-16-2012 at 03:51 PM.

  9. #9
    Registered User
    Join Date
    May 2012
    Location
    Italy
    Posts
    52
    Mmm ok....i've understood! Thanks a lot!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. fread, fwrite
    By thescratchy in forum C Programming
    Replies: 2
    Last Post: 03-17-2010, 10:01 AM
  2. fread/fwrite
    By chopficaro in forum C Programming
    Replies: 6
    Last Post: 05-11-2008, 02:48 AM
  3. fwrite and fread help
    By jverkoey in forum C++ Programming
    Replies: 2
    Last Post: 02-12-2003, 10:17 PM
  4. fwrite and fread
    By condorx in forum C Programming
    Replies: 5
    Last Post: 06-08-2002, 01:01 AM
  5. fread() and fwrite() ?
    By Limblet in forum C Programming
    Replies: 4
    Last Post: 09-25-2001, 08:36 PM

Tags for this Thread


1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21