Thread: reading binary file with different data types

  1. #1
    Registered User
    Join Date
    Jul 2008
    Location
    Barcelona
    Posts
    41

    reading binary file with different data types

    Hello,
    I am new to C and I am trying to read a binary file with different data types. The first data types are specified as:
    HeaderVersion unsigned char 1
    HeaderSize unsigned long 4
    DataFormat unsigned char 1
    raw_data_file_name char 80

    I cant seem to make it work. I get strange results when I try to print results to screen. Any suggestions? Thanks
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    #include <malloc.h>
    #include <conio.h>
    
    
    void main()
    {
    	// declarations
    	FILE *file_in, *file_out;
    	char inpfile[200], name_file_out[210], raw_data_file_name[80];
    	unsigned char header_version[1], data_format[1];
    	unsigned long int header_size;
    	
    
    	printf(" Input binary file\n");
    	scanf("%s", &inpfile);
    
    	strcpy(name_file_out, "out_");
    	strcat(name_file_out, inpfile);	
    	printf(" Output file with amplitude: %s\n", name_file_out);
    
    	if (!(file_in = fopen (inpfile, "rb")))
    	{	
    		printf("\nCannot open the input file - image file\n");
    		exit(0);
    	}	
    
    	fread(header_version, sizeof(unsigned char), 1, file_in);
    	fread(header_size, sizeof(unsigned long int), 1, file_in);
    	fread(data_format, sizeof(unsigned char), 1, file_in);
    	fread(raw_data_file_name, sizeof(char), 1, file_in);
    
    	printf("%c\n", header_version);
    	printf("%li\n", header_size);
    	printf("%c\n", data_format);
    	printf("%c\n", raw_data_file_name);
    
    	fclose(file_in);
    
    }

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I strongly suspect that this isn't what you wanted to do:
    Code:
    fread(raw_data_file_name, sizeof(char), 1, file_in);

    And I would be very surprised if this compiles without warnings, and it's VERY likely to crash:
    Code:
    		fread(header_size, sizeof(unsigned long int), 1, file_in);
    Code:
    #include <conio.h>
    Why?

    Code:
    #include <stdlib.h>
    ... 
    #include <malloc.h>
    malloc is declared in stdlib.h - so no need to use the deprecated malloc.h header...

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Jul 2008
    Location
    Barcelona
    Posts
    41
    Thank for the reply! You are right
    Code:
    fread(header_size, sizeof(unsigned long int), 1, file_in);
    does compile with warnings. But even if I disable that line I still get strange results like:

    Input binary file
    a
    Output file with amplitude: out_a
    ê
    ä
    î
    Press any key to continue

    I must be missing something fundamental =/ and btw how should I correctly read an "unsigned long int"?

  4. #4
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Well, that's hardly surprising, as that line will also move your file-pointer forward 4 bytes, so if you just "remove" that line, anything you read after that line is going to be off by 4. That's like saying go to page 45, but you start reading on page 41 instead in the book - you won't find the same thing as you expect.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  5. #5
    Registered User
    Join Date
    Jul 2008
    Location
    Barcelona
    Posts
    41
    Thank you for your reply!
    I understand what you mean about the "pages of the book" now. Still when I try to print to screen what has been read into the buffers I get strange results except for the normal "chars".
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    
    void main()
    {
    	// declarations
    	FILE *file_in;
    	char inpfile[200], name_file_out[210], *raw_data_file_name, *site_name;
    	unsigned char *header_version, *data_format;
    	unsigned long *header_size, *site_id;
    	
    	printf(" Input binary file\n");
    	scanf("%s", &inpfile);
    
    	strcpy(name_file_out, "out_");
    	strcat(name_file_out, inpfile);	
    	printf(" Output file with amplitude: %s\n", name_file_out);
    	if (!(file_in = fopen (inpfile, "rb")))
    	{	
    		printf("\nCannot open the input file - image file\n");
    		exit(0);
    	}
    	
    	/********** allocations ****************/
    	header_version = (unsigned char *) malloc (1*sizeof(unsigned char));
    	header_size = (unsigned long *) calloc (1,sizeof(unsigned long));
    	data_format = (unsigned char *) malloc (1*sizeof(unsigned char));
    	raw_data_file_name = (char *) malloc (90*sizeof(char));
    	site_name = (char *) malloc (30*sizeof(char));
    	site_id = (unsigned long *) calloc (4,sizeof(unsigned long));
    
    	/********** read binary ****************/
    	fread((unsigned char *) header_version, sizeof(unsigned char), 1, file_in);
    	fread((unsigned long *) header_size, sizeof(unsigned long), 1, file_in);
    	fread((unsigned char *) data_format, sizeof(unsigned char), 1, file_in);
    	fread((char *) raw_data_file_name, sizeof(char), 80, file_in);
    	fread((char *) site_name, sizeof(char), 24, file_in);
    	fread((unsigned long *) site_id, sizeof(unsigned long), 1, file_in);
    
    	/********** print **************/
    	printf("%s\n", header_version);
    	printf("%ld\n", header_size);
    	printf("%s\n", data_format);
    	printf("%s\n", raw_data_file_name);
    	printf("%s\n", site_name);
    	printf("%ld\n", site_id);
    
    	fclose(file_in);
    
    }
    the output is:
    Input binary file
    a
    Output file with amplitude: out_a
    ☻²²²²
    4399040
    ♥²²²²
    000001 - 2008.07.25 - 16.57.28 - nch3
    ══════════²²²²
    nch3 ══════²²²²
    4398704
    Press any key to continue

  6. #6
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    printf doesn't take pointers to information, it takes the information itself. So send it *header_size and *site_id.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
    fread((unsigned long *) header_size, sizeof(unsigned long), 1, file_in);
    Why do you have the cast in there - header_size is a pointer already.

    What do you expect from the char values - you are printing a string, but you only read one char. Is it a char that actually represent a value in the printable range, or just a "char for size, bur really just a small integer" (e.g. values lower than 32 or higher than 126)? If so, you could just use %d formatting.

    Code:
    unsigned long *header_size, *site_id;
    ...
    header_size = (unsigned long *) calloc (1,sizeof(unsigned long));
    ... 
    fread((unsigned long *) header_size, sizeof(unsigned long), 1, file_in);
    This is quite a complicated way of getting the address of a unsigned long. What's wrong with using the address-of operator:
    Code:
    unsigned long header_size, *site_id;
    ...
    fread(&header_size, sizeof(unsigned long), 1, file_in);
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Jul 2008
    Location
    Barcelona
    Posts
    41
    Thanks again for your answer! I want the chars to display a character (though it might be number). I changed my "longs" to your recommendation. They show the expected result.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    #include <string.h>
    
    void main()
    {
    	// declarations
    	FILE *file_in;
    
    	char inpfile[200], name_file_out[210], *raw_data_file_name, *site_name;
    	unsigned char *header_version, *data_format;
    	unsigned long header_size, site_id;
    	
    	printf(" Input binary file\n");
    	scanf("%s", &inpfile);
    
    	strcpy(name_file_out, "out_");
    	strcat(name_file_out, inpfile);	
    	printf(" Output file with amplitude: %s\n", name_file_out);
    	if (!(file_in = fopen (inpfile, "rb")))
    	{	
    		printf("\nCannot open the input file - image file\n");
    		exit(0);
    	}
    	
    	/********** allocations ****************/
    	header_version = (unsigned char *) malloc (1*sizeof(unsigned char));
    	header_size = (unsigned long) calloc (1,sizeof(unsigned long));
    	data_format = (unsigned char *) malloc (1*sizeof(unsigned char));
    	raw_data_file_name = (char *) malloc (81*sizeof(char));
    	site_name = (char *) malloc (25*sizeof(char));
    	site_id = (unsigned long) calloc (4,sizeof(unsigned long));
    
    	/********** read binary ****************/
    	fread((unsigned char *) header_version, sizeof(unsigned char), 1, file_in);
    	fread(&header_size, sizeof(unsigned long), 1, file_in);
    	fread((unsigned char *) data_format, sizeof(unsigned char), 1, file_in);
    	fread((char *) raw_data_file_name, sizeof(char), 80, file_in);
    	fread((char *) site_name, sizeof(char), 24, file_in);
    	fread(&site_id, sizeof(unsigned long), 1, file_in);
    
    	/********** print **************/
    	printf("%c\n", header_version);
    	printf("%ld\n", header_size);
    	printf("%c\n", data_format);
    	printf("%s\n", raw_data_file_name);
    	printf("%s\n", site_name);
    	printf("%ld\n", site_id);
    
    	fclose(file_in);
    
    }
    with output:
    Input binary file
    a
    Output file with amplitude: out_a
    ..
    240
    É
    000001 - 2008.07.25 - 16.57.28 - nch
    ═²²²²
    nch3 ═²²²²
    1496
    Press any key to continue

    I know 240 is correct, as is "000001 - 2008.07.25 - 16.57.28 - nch" and "nch3". But what is that junk ═²²²² doing there? header_version should be "2", but it doesnt show. Obviously my c skills are not what I'd wish they were =/

  9. #9
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    I can't say for sure, but I suspect your junk is coming from a string being stored in the file without a zero at the end, and you end up printing the string until the first zero byte, so you get a few extra zeros. Try using calloc() instead of malloc() for your strings.

    As to your %c formatted printf, you are passing the address and showing that as a char - so it will not show what was in your file, but the char representation of your memory location - which is highly unlikely to be what you wanted.

    Code:
    	unsigned long header_size, site_id;
    ...
    	header_size = (unsigned long) calloc (1,sizeof(unsigned long));
    ...
            site_id = (unsigned long) calloc (4,sizeof(unsigned long));
    ...
    	fread(&header_size, sizeof(unsigned long), 1, file_in);
    	fread(&site_id, sizeof(unsigned long), 1, file_in);
    ...
    No, no. You are allocating memory, then casting it to a unsigned long, then overwriting that unsigned long value with what is in your file. You don't need the calloc here (also, why are you calloc'ing 4 elements for site_id?)

    If your file is called something .c, then you should not need to cast any of the results of malloc/calloc, it should all work just fine with ptr = malloc(...). If the compiler complains about that, then you are probably doing something wrong - the correct solution at that point is not to add a cast [unless you REALLY understand what you are doing].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading from a file and using the data
    By Ste_Mulv in forum C Programming
    Replies: 3
    Last Post: 04-01-2009, 07:44 AM
  2. Reading multiple data types to file
    By Wicket in forum C++ Programming
    Replies: 2
    Last Post: 04-05-2008, 10:14 AM
  3. Problems in reading binary file
    By serena in forum C Programming
    Replies: 3
    Last Post: 04-14-2005, 03:54 AM
  4. Request for comments
    By Prelude in forum A Brief History of Cprogramming.com
    Replies: 15
    Last Post: 01-02-2004, 10:33 AM
  5. File Database & Data Structure :: C++
    By kuphryn in forum C++ Programming
    Replies: 0
    Last Post: 02-24-2002, 11:47 AM

Tags for this Thread