Thread: Reading/writing a file containing multiple NULLs into buffer

  1. #1
    Registered User
    Join Date
    Dec 2011
    Posts
    5

    Reading/writing a file containing multiple NULLs into buffer

    Hi all,

    I am trying to read a binary file containing multiple NULL characters into a char buffer. I was hoping to use fseek() and ftell() to read the size of the file, and use the reported filesize to allocate memory to the buffer (to contain the full size of the file, of course). But since fseek() terminates on the first occurrence of a NULL byte, I'm only able to read the first little segment of my file.

    What would be the best way of reading in the ENTIRE file into memory, NULLs and all, until EOF?

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,632
    The fseek() function does not give a hoot about NULL characters. How are you trying to read this file? How are you opening the file? Show us the code that is giving you the problems, along with a small sample of your input file and any error messages you receive when you compile.

    Jim

  3. #3
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by cocobean View Post
    But since fseek() terminates on the first occurrence of a NULL byte, I'm only able to read the first little segment of my file.
    Where did you get that info from? Best not to use that source again. fseek doesn't stop at null bytes:
    Quote Originally Posted by man fseek
    DESCRIPTION
    The fseek() function sets the file position indicator for the stream pointed
    to by stream. The new position, measured in bytes, is obtained by adding
    offset bytes to the position specified by whence. If whence is set to
    SEEK_SET, SEEK_CUR, or SEEK_END, the offset is relative to the start of the
    file, the current position indicator, or end-of-file, respectively. A
    successful call to the fseek() function clears the end-of-file indicator for
    the stream and undoes any effects of the ungetc(3) function on the same
    stream.
    Also, what are you using to read from the file? Your read function may be what's stopping at the null bytes.

    What would be the best way of reading in the ENTIRE file into memory, NULLs and all, until EOF?
    fseek is the most portable way to get the size, but make sure you don't leave the file pointer at the end of the file when trying to read (i.e. call fseek(fp, 0, SEEK_SET)). Then, since it's binary data, you have to use fread to read.

  4. #4
    Registered User
    Join Date
    Dec 2011
    Posts
    5
    As an experiment, I'm actually trying to have the code read itself into a buffer, like so:

    Code:
    void Copy_file() {
        char filename[1024];
        unsigned char *buffer;
        unsigned long fileLen;
        size_t len = 0;
        FILE * file_src;
        FILE * file_dst;
    
        /* Get path */
        GetModuleFileName(NULL,filename,1024);
    
        file_src = fopen(filename,"rb");
        if (!file_src) {
            fprintf(stderr,"Cannot open source file %s.\n",filename);
            return;
        }
    
        /* Get file length */
        fseek(file_src,0,SEEK_END);
        fileLen = ftell(file_src);
        fseek(file_src,0,SEEK_SET);
    
        /* Allocate memory */
        buffer = (char*)malloc(fileLen+1);
        printf("strlen(buffer) == %d\n",strlen(buffer));
    There's more, but I believe the problem is due to something in the above code. No compilation errors occur, nor does my code get caught in any of my error checking.

    At this point, strlen(buffer) is 3. The code does actually write out the file, but inspecting its content in a text editor, the only content is the MZ signature, "MZ". The original binary file contains "MZ\0..." and it continues from there. My assumption was that somewhere along the line, the file is being read only up until the NULL.

  5. #5
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    You're allocating an uninitialized buffer and then calling strlen() on it! You need to do your fread before doing anything else with the buffer:size_t n = fread(buffer, 1, fileLen, file_src);And you won't actually be able to use the string functions on your buffer because THEY definitely stop at null chars. Just treat it as an array of chars and use the fileLen to not read past the end.

  6. #6
    Registered User
    Join Date
    Dec 2011
    Posts
    5
    Ah! I see, thank you, I have updated it. Now the length of the file is correct, but the content of the output file is not right. This is the current code:

    Code:
    void Copy_file() {
        char filename[1024];
        unsigned char *buffer;
        unsigned long fileLen;
        size_t len = 0;
        size_t n;
        FILE * file_src;
        FILE * file_dst;
    
    
        /* Get path */
        GetModuleFileName(NULL,filename,1024);
        printf("Launch point: %s\n",filename);
    
        file_src = fopen(filename,"rb");
        if (!file_src) {
            fprintf(stderr,"Cannot open source file %s.\n",filename);
            return;
        }
    
        /* Get file length */
        fseek(file_src,0,SEEK_END);
        fileLen = ftell(file_src);
        fseek(file_src,0,SEEK_SET);
    
        printf("FileLen: %d\n",fileLen);
    
        /* Read file contents into buffer */
        n = fread(buffer, 1, fileLen, file_src);
    
        /* Allocate memory */
        buffer = (char*)malloc(n);
        if (!buffer) {
            fprintf(stderr, "Memory allocation error.\n");
            fclose(file_src);
            return;
        }
    
        /* Open output file */
        file_dst = fopen("C:\\test.exe","wb");
        if (!file_dst) {
            printf("Cannot copy destination file.\n");
            fclose(file_src);
            return;
        }
        
        /* Write output file */    
        int c;
        while ((c = getc(file_src) != EOF)) {
            putc(c, file_dst);
        }
    
        free(buffer);
        fclose(file_src);
        fclose(file_dst);
    
        printf("File copy complete.\n"); 
        
        return;
    }

  7. #7
    Registered User
    Join Date
    Dec 2011
    Posts
    5
    I'm getting strange results. When I use fread() to store my file in my buffer, running a sizeof() on it produces a value of 4. Also, correct me if I'm wrong, but I think the correct sequence of events is:


    1. open file (read/binary mode)
    2. get length of file
    3. allocate buffer memory
    4. copy file into buffer
    5. open output file (write/binary mode)
    6. write buffer to output file


    I've done this, so I just don't see what I'm doing wrong here. Again, no compilation errors, and I'm not getting caught in any self-coded error checks. Here is the current code:

    Code:
    void Copy_file() {
        char filename[1024];
        char *buffer;
        long lSize;
        size_t result;
        FILE * file_src;
        FILE * file_dst;
    
        /* Get path */
        GetModuleFileName(NULL,filename,1024);
    
        file_src = fopen(filename,"rb");
        if (file_src == NULL) {
            fprintf(stderr,"Cannot open source file %s.\n",filename);        
            return;
        }
    
        /* Get file size */
        fseek(file_src,0,SEEK_END);
        lSize = ftell(file_src);
        rewind(file_src);
    
        printf("lSize: %d\n",lSize);                                // prints 28792
    
        /* Allocate memory to contain file*/
        buffer = (char*) malloc (sizeof(char) *lSize);
        if (buffer == NULL) {
            fprintf(stderr, "Memory allocation error.\n");
            fclose(file_src);
            return;
        }
    
        /* Copy file into buffer */
        result = fread(buffer, 1, lSize, file_src);
        if (result != lSize) {
            ("Reading error.\n",stderr); 
            return;
        }
        printf("sizeof(result) == %d\n",sizeof(result));               // prints 4
    
        /* Open output file */
        file_dst = fopen("C:\\test.exe","wb");
        if (!file_dst) {
            printf("Cannot copy destination file.\n");
            fclose(file_src);
            return;
        }
        
        /* Write output file */
        fwrite(buffer, 1, sizeof(buffer), file_dst);
        printf("sizeof(buffer) == %d\n",sizeof(buffer));           // prints 4
    
        free(buffer);
        fclose(file_src);
        fclose(file_dst);
    
        printf("File copy complete.\n"); 
        
        return;
    }
    Last edited by cocobean; 12-22-2011 at 10:18 PM.

  8. #8
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Code:
    fwrite(buffer, 1, sizeof(buffer), file_dst);
    You know sizeof() is NOT right; why are you using it?
    Use the size of the file (lSize).

    NOTE: The size of a pointer DOES NOT change because it points to a larger allocated area.

    Tim S.

  9. #9
    Registered User
    Join Date
    Dec 2011
    Posts
    5
    Quote Originally Posted by stahta01 View Post
    Code:
    fwrite(buffer, 1, sizeof(buffer), file_dst);
    You know sizeof() is NOT right; why are you using it?
    Use the size of the file (lSize).

    NOTE: The size of a pointer DOES NOT change because it points to a larger allocated area.

    Tim S.
    *facepalm* Silly me. It works perfectly, thanks stahta01!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 2
    Last Post: 02-25-2010, 03:54 AM
  2. File being filled with NULLs
    By Tigers! in forum Windows Programming
    Replies: 2
    Last Post: 06-30-2009, 05:28 PM
  3. Writing/Reading multiple files...??
    By audinue in forum C Programming
    Replies: 3
    Last Post: 07-28-2008, 11:14 PM
  4. writing a file from buffer
    By mariano_donati in forum C Programming
    Replies: 8
    Last Post: 02-25-2008, 02:04 AM
  5. Writing to single file in multiple functions
    By alvision in forum C Programming
    Replies: 12
    Last Post: 08-22-2004, 08:15 PM