Thread: Binary File I/O Problem

  1. #1
    Registered User
    Join Date
    Apr 2004
    Posts
    173

    Binary File I/O Problem

    Lets say I have the following code:

    Code:
    struct node {
     int length;
     int *msg;
     struct node* next;
    };
    Now I have the following:

    Code:
    // Some code here
    fp = fopen(argv[i],"rb");
    struct node* new = malloc(sizeof(struct node));
    new->msg = malloc(sizeof(int)*(new->length));  // say you already got a length
    items_read = fread(new->msg, sizeof(new->msg),1,fp);
    I'm having trouble printing out the contents of the integer array msg. It seems to only print the first character/integer. I sprinkled a printf() to see what my value of length was and it was correct but for some reason I can't seem to get msg to print, using arrays, using pointers and using fwrite() to stdout. I'm not entirely sure if my fread() arguments are correct but I thought it could be due to msg being a pointer and sizeof() that would only be one. But I tried sizeof(*(new->msg)) to no avail.

    Any ideas?

  2. #2
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    your idea about your sizeof() in the fread() being wrong is correct. think; what variable types are new->msg and *(new->msg)?
    hello, internet!

  3. #3
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    items_read = fread(new->msg,sizeof(new->msg),1,fp);
    You are reading in 1 item of the size of a pointer (may be different from the size of an int?). You need to read in length items of whatever your int size happens to be. I believe you want:

    Code:
    items_read = fread(new->msg,sizeof(int),new->length,fp);
    Last edited by hk_mp5kpdw; 08-30-2004 at 10:19 AM.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  4. #4
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    Hmm damn, this thing is cursing me.. that doesn't work either it should but it doesn't - argh don't want to put in all of my code because its kinda too long.
    Im totally confused..

    Ok, heres a bit of my code just to clarify a bit: it looks slightly different to the example I put above but I didn't think it would really matter:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <time.h>
    #include <ctype.h>
    #include "codeops.c"
    
    struct message {
        time_t time;
        char location[24];
        int device_id;
        double frequency;
        int burst_size;
        int msg_len;
    };    
    
    struct node {
        struct message data;
        int* msg;
        struct node* next;
    };
    
    int main(int argc, char **argv)
    {
        int i = 1, items_read = 0,j = 0;
        struct node *empty = NULL;
        struct node *new = (struct node*)malloc(sizeof(struct node)); 
        /* Check for arguments if argc == 1 display usage */
        if (argc == 1){
            printf("usage: codebreak messagefile\n");
            printf("where: messagefile contains intercepts in the correct binary format\n");
            return 0;
        }
    	FILE *fp; 
    
    	while (i < argc){
    	fp = fopen(argv[i],"rb");
    	i++; 
    
    	items_read = fread(new,(sizeof(new->data)),1,fp);
    	if (items_read != 1)
    		break;
    	new->msg = malloc(sizeof(int)*(new->data.msg_len+1));
    	items_read = fread(new->msg,sizeof(int),new->data.msg_len,fp);
    
    	printf("Msg_len: %d\n",new->data.msg_len); // debugging printf()
    	
    	printf("%s",new->msg);	 // debugging printf()
    	sorted_insert(&empty,new);
    	}        
        print_list(empty);
        free_list(&empty);
        return 0;
    }
    The functions sorted_insert(), print_list() and free_list() does as the name suggested.
    Last edited by 0rion; 08-30-2004 at 10:40 AM.

  5. #5
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    I don't know if this is going to help you. I had a similar problem last year. I modified my code to help you so here it is:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct node{
    	int len;
        int* msg;
        struct node* next;
    }Node,*pNode;
    
    int main(int argc, char **argv)
    {
    	int i;
    	pNode n,m;
    	int array[]={1,2,3,4,5};
    	FILE* fp= fopen("Test.bin","wb");
    	if(!fp)
    	{
    		fprintf(stderr,"Error!");
    		return 0;
    	}
    	n=(pNode)malloc(sizeof(Node));
    	n->msg=(int*)malloc(sizeof(int)*5);
    	memcpy(n->msg,array,sizeof(int)*5);
    	n->len=5;
    	n->next=NULL;
    	fwrite(&(n->len),sizeof(n->len),1,fp);
    	for(i=0;i<n->len;i++)
    		fwrite(&(n->msg[i]),sizeof(n->msg[i]),1,fp);
    	fwrite(&(n->next),sizeof(n->next),1,fp);
    	fclose(fp);
    	fp=fopen("Test.bin","rb");
    	if(!fp)
    	{
    		fprintf(stderr,"Error!");
    		return 0;
    	}
    	m=(pNode)malloc(sizeof(Node));
    	fread(&i,sizeof(i),1,fp);
    	m->len=i;
    	m->msg=(int*)malloc(sizeof(int)*i);
    	for(i=0;i<m->len;i++)
    		fread(&(m->msg[i]),sizeof(m->msg[i]),1,fp);
    	fread(&(m->next),sizeof(m->next),1,fp);
    	for(i=0;i<m->len;i++)
    		printf("%d",m->msg[i]);
    
    	//free allocated memory
    
    }
    It may have some problems, but like I said it was a long time ago.
    Anyway, I hope this will help you!
    GoodLuck!

  6. #6
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    #include "codeops.c"
    You really should not be including c source files. If your project is a multi-file project then compile/link it as such.

    Also, are you positive that your code that writes the file is working properly? Could we also see that code?


    Code:
    	items_read = fread(new->msg,sizeof(int),new->data.msg_len,fp);
    
    	printf("Msg_len: %d\n",new->data.msg_len); // debugging printf()
    As an additional debug check, you can also print out the return value of the fread, i.e. items_read and see if that goes along with what you are expecting.


    Code:
    printf("%s",new->msg);	 // debugging printf()
    What do you expect this to do? msg is an int pointer and you are telling printf to expect a character string.

    If there is not too much data to read into your list, you can try printing out the list as each successive record is read from the file and inserted into the list. This may necessitate temporarily changing the print routine so that it pauses after displaying each node of the list to allow you to debug better.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  7. #7
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    About the printing the int pointer as a string - it was in the specifications of the assignment so I have to use it like that. I tried using a for loop to control and print each int element (into char) to no success as well.

    Ahh, I"m not so much writing to a file I'm just reading a file and storing it into a linked list. As for the file itself, it's not readable since its a binary file - it was provided to us to check if our program works

    Ah thanks Micko I'll look into your code shortly

  8. #8
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    I'm not sure if you wanted me to post the code on the print_list() and sorted_insert() hk_mp5kpdw, but here they are anyway:

    Code:
    void print_list(struct node* root)
    {
            if (root == NULL){
                printf("Nothing to print! Empty list!\n");
                return;
            }    
            struct node* current = root;
            while (current != NULL){
                printf("%s %s/%d %s\n",timestamp((current->data).time),
                (current->data).location, (current->data).device_id,
                (current->msg));
                
                current = current->next;
            }
    }  
    
    void sorted_insert(struct node **headRef, struct node *newNode)
    {
    	struct node** currentRef = headRef;
    	
    	/* traverse the tree */
    	while (*currentRef != NULL && (int)((*currentRef)->data.time) > (int)(newNode->data.time))
    	currentRef = &((*currentRef)->next);
    
    	/* insert here */
    	newNode->next = *currentRef;
    	*currentRef = newNode;
    }
    Ok, I have NO idea whats going on but I just used a for loop to print each new->msg[j] element and it works, I tried it last nite but it didn't work.. argh its toying with me
    Last edited by 0rion; 08-30-2004 at 06:51 PM.

  9. #9
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Quote Originally Posted by Orion
    Ok, I have NO idea whats going on but I just used a for loop to print each new->msg[j] element and it works, I tried it last nite but it didn't work..
    Quote Originally Posted by Orion
    About the printing the int pointer as a string - it was in the specifications of the assignment so I have to use it like that. I tried using a for loop to control and print each int element (into char) to no success as well.
    It did or it didn't work?

    You may need to post your complete source code and the input file zipped up as an attachment. Looks almost like the msg field is supposed to point to a bunch of character data and not integers. Maybe also include as much as you can about the "specification".
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  10. #10
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    I should of made myself more clear, it works now
    The specification just said:

    msg: The message content is a sequence of msg_len integers. type: int[]

    I'm not sure why its int instead of char, but I read somewhere that for binary files (or text files in general) an integer is favoured over a character since you can determine the EOF without conflicting with one of the binary values for a particular character. Which is probably why EOF is sometimes -1, since there is no character for -1 in the character set, but then again I could be purely wrong
    Last edited by 0rion; 08-31-2004 at 06:11 AM.

  11. #11
    Registered User Micko's Avatar
    Join Date
    Nov 2003
    Posts
    715
    Quote Originally Posted by 0rion
    I'm not sure why its int instead of char, but I read somewhere that for binary files (or text files in general) an integer is favoured over a character since you can determine the EOF without conflicting with one of the binary values for a particular character. Which is probably why EOF is sometimes -1, since there is no character for -1 in the character set, but then again I could be purely wrong
    Code:
    char ch;
    while( (ch = fgetc(fp)) != EOF ) {
    /*_ do something with ch _*/
    }
    There is a common C programming bug that directly relates to this
    subject.
    The prototype of fgetc()is:
    int fgetc( FILE * );
    One might question why does the function return back an int since it reads
    characters? The reason is that it normally does return back an char (extended
    to an int value using zero extension). However, there is one value
    that it may return that is not a character, EOF. This is a macro that is
    usually defined as −1. Thus, fgetc() either returns back a char extended
    to an int value (which looks like 000000xx in hex) or EOF (which looks like
    FFFFFFFF in hex).
    The basic problem with the program is that fgetc() returns
    an int, but this value is stored in a char. C will truncate the higher
    order bits to fit the int value into the char. The only problem is that the
    numbers (in hex) 000000FF and FFFFFFFF both will be truncated to the
    byte FF. Thus, the while loop can not distinguish between reading the byte
    FF from the file and end of file.
    Exactly what the code does in this case, depends on whether char is
    signed or unsigned. Why? Because in line 2, ch is compared with EOF.
    Since EOF is an int value1, ch will be extended to an int so that two values
    being compared are of the same size.
    If char is unsigned, FF is extended to be 000000FF. This is compared to
    EOF (FFFFFFFF) and found to be not equal. Thus, the loop never ends!
    1It is a common misconception that files have an EOF character at their end. This is
    not true!
    If char is signed, FF is extended to FFFFFFFF. This does compare as
    equal and the loop ends. However, since the byte FF may have been read
    from the file, the loop could be ending prematurely.
    The solution to this problem is to define the ch variable as an int, not a
    char. When this is done, no truncating or extension is done in line 2. Inside
    the loop, it is safe to truncate the value since ch must actually be a simple
    byte there.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Can we have vector of vector?
    By ketu1 in forum C++ Programming
    Replies: 24
    Last Post: 01-03-2008, 05:02 AM
  2. gcc link external library
    By spank in forum C Programming
    Replies: 6
    Last Post: 08-08-2007, 03:44 PM
  3. Basic text file encoder
    By Abda92 in forum C Programming
    Replies: 15
    Last Post: 05-22-2007, 01:19 PM
  4. File I/O problem
    By dacbo in forum C Programming
    Replies: 4
    Last Post: 01-17-2006, 08:22 AM
  5. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM