Thread: setting a position in a binary file

  1. #1
    Registered User
    Join Date
    Jan 2013
    Posts
    42

    setting a position in a binary file

    I have a program that I am writing fro school. In this program, I create a Struct of type person[1000]. The struct holds various data char *, ints and floats. I have no problems writing to the binary file and displaying all the contents in the file.

    In another function I need to open the binary file and retrieve particular data from it. The data I need lies in byte position 37-40. I would then need to increment the position by 56 bytes to get the data from 97-100 and basically keep doing this until the end of file is reached.

    I have been reading up on fseek but it doesnt appear that I can actually pass it a manual position. There are only the three options for the whence. Do I need to use another option to set the position? Any help would be appreciated.

    Thanks,

    Michael

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Apparently, you haven't read the documentation for fseek() all that closely. Either use fseek(file, 56, SEEK_CUR) after reading the data in position 37-40, or fseek(file, 97, SEEK_SET) to position relative to the start of the file.

    If you're reading multiple data structures, each struct will be sizeof(your structure) bytes in length. So add an appropriate multiple and use positioning relative to the start of the file to position for the data in position 37-40.

    Your description "manual position" is meaningless.

    Note that if the structure contains pointers, the file will contain the value of the pointers, not whatever those pointers point at.
    Last edited by grumpy; 02-23-2013 at 02:03 AM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > The struct holds various data char *, ints and floats.
    Therein lies the problem.

    You can't just fwrite the contents of a struct, if it contains pointers.
    Code:
    struct foo {
       char *a;
    } bar;
    bar.a = malloc(100);
    strcpy(bar.a,"this is a really long string");
    fwrite(&bar,sizeof(bar),1,fp);
    It will fwrite the pointer, but you won't see your string in the file.
    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.

  4. #4
    Registered User
    Join Date
    Jan 2013
    Posts
    42
    I had actually tried that but I never did a fread to store the data and print it to the screen to verify that it was right. Way too many hours in front of the screen today. I've been running some tests and I am getting the values I want, now I just need to loop through the file to get all of my values. Do you know a good EOF alternative for binary files.

  5. #5
    Registered User
    Join Date
    Jan 2013
    Posts
    42
    Quote Originally Posted by Salem View Post
    > The struct holds various data char *, ints and floats.
    Therein lies the problem.

    You can't just fwrite the contents of a struct, if it contains pointers.
    Code:
    struct foo {
       char *a;
    } bar;
    bar.a = malloc(100);
    strcpy(bar.a,"this is a really long string");
    fwrite(&bar,sizeof(bar),1,fp);
    It will fwrite the pointer, but you won't see your string in the file.
    That is actually not a problem, I have no problems storing the Struct in the binary file and retrieving it. The string name gets displayed fine for all my entries.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    So exactly how are you serialising the struct then?

    If you have (as a result) variable length records because you're outputting variable length strings, then using fseek() to go to a particular record suddenly becomes a far less easy thing to do.
    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.

  7. #7
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by generaltso78 View Post
    That is actually not a problem, I have no problems storing the Struct in the binary file and retrieving it. The string name gets displayed fine for all my entries.
    Really? That means you are using arrays rather than pointers (which is fine) or you have a critically flawed program with symptoms that have yet to emerge.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  8. #8
    Registered User
    Join Date
    Mar 2010
    Posts
    583
    Are they actually char* s or fixed length char arrays?

    Quote Originally Posted by generaltso78
    Do you know a good EOF alternative for binary files.
    Check that the return value from fread is what you expected it to be. If it's not, check ferror() and feof() like you would for a text file.

  9. #9
    Registered User
    Join Date
    Jan 2013
    Posts
    42
    Yes, The structs are stored in a array and then written to binary file. The Struct contains a char[20], 4 ints and 6 floats. Every time a struct is stored the file size increments by 60 bytes. This is still uncharted territory for me, so bare with my terminology. I made a variable to contain my byte location for fseek. That way I can increment the position through a loop as I run through the file. I haven't figured out the exact increment size Im looking for yet, so I need to keep playing with it. My big concern is that when I increment my byte location variable than eventually fseek will move beyond the end of file and return a value that I am not looking for (would this happen before my EOF condition is triggered?)
    Last edited by generaltso78; 02-23-2013 at 10:54 AM.

  10. #10
    Registered User
    Join Date
    Jan 2013
    Posts
    42
    This is where my program pushes my mental limits.

    Code:
    void totalRegularPay(EMPLOYEE person[]){
    	int i = 0, bP = 36;
    	float payrollTotals[1000];
    	FILE *f;
    	f = fopen("employeeRecords.bin", "rb");
    	
    	while (!feof(f)) {
    		fseek(f, bP, SEEK_CUR);
    		fread(&payrollTotals[i], sizeof(float), 1, f);
    		printf("%.2f", payrollTotals[i]);
    		i++;
    		bP += 20;
    	}
    	fclose(f);
    	pause;
    }
    The positions I want are at 36, 96, 156, 216, 276, etc..... Obviously, my sad attempt at += 20 only works for the next position. I'm thinking I may need to reset the binary position back to 0 after every fseek and then increment my bP(36) by 60.

  11. #11
    Registered User
    Join Date
    Jan 2013
    Posts
    42
    sorry, obviously while (!feof(F)) is not going to work

  12. #12
    Registered User
    Join Date
    May 2012
    Posts
    1,066
    Quote Originally Posted by generaltso78 View Post
    The positions I want are at 36, 96, 156, 216, 276, etc..... Obviously, my sad attempt at += 20 only works for the next position. I'm thinking I may need to reset the binary position back to 0 after every fseek and then increment my bP(36) by 60.
    As far as I understand your problem you want to get one specific float value from each record, right?
    So why don't you read one full record after another (into a temporary struct object) and extract the value you are interested in? Should be very easy and straight forward.

    Bye, Andreas

  13. #13
    Registered User
    Join Date
    May 2012
    Posts
    505
    Quote Originally Posted by generaltso78 View Post
    Yes, The structs are stored in a array and then written to binary file. The Struct contains a char[20], 4 ints and 6 floats. Every time a struct is stored the file size increments by 60 bytes. This is still uncharted territory for me, so bare with my terminology. I made a variable to contain my byte location for fseek. That way I can increment the position through a loop as I run through the file. I haven't figured out the exact increment size Im looking for yet, so I need to keep playing with it. My big concern is that when I increment my byte location variable than eventually fseek will move beyond the end of file and return a value that I am not looking for (would this happen before my EOF condition is triggered?)
    You need to use the sizeof() operator to get the size of your struct. Manually adding the field sizes might not give the right size because of padding. You should then read a whole struct in and out of the binary file. Whilst you can read a field, it's easy to get it subtly wrong.
    The equation is simply pos = sizeof(the_struct) * index;
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  14. #14
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by generaltso78 View Post
    This is where my program pushes my mental limits.
    So your mental limits are pushed by the need to retrieve a particular field from a repeated series of structs? I've heard of pretty low limits in my time .....

    Quote Originally Posted by generaltso78 View Post
    The positions I want are at 36, 96, 156, 216, 276, etc..... Obviously, my sad attempt at += 20 only works for the next position. I'm thinking I may need to reset the binary position back to 0 after every fseek and then increment my bP(36) by 60.
    If you really want to unnecessarily reduce performance of your program when reading, go for it.

    Your basic problem is that you're not taking into account the fact that, after fread(), the file pointer will be incremented by the amount successfully read. Either that or you don't understand that relative and absolute positioning in a file are related by a subtraction.

    If positioning with fseek() is beyond you, AndiPersti's approach will also work.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  15. #15
    Registered User
    Join Date
    Jan 2013
    Posts
    42
    The problem turned out to be as easy as replacing my eof condition and implenting another fseek to run before the loop.

    Code:
    void totalRegularPay(EMPLOYEE person[]){
    	int i = 0, bP =36;
    	float payrollTotals[1000];
    	FILE *f;
    	f = fopen("employeeRecords.bin", "rb");
    	fseek(f, 36, SEEK_SET);
    	while (fread(&payrollTotals[i], sizeof(int), 1, f) == 1){
    		
    		printf("$%.2f", payrollTotals[i]);
    		i++;
    		bP += 60;
    		fseek(f, bP, SEEK_SET);
    	}
    	fclose(f);
    	pause;
    }
    I have only had it tested running through eight structs but i seems to be returning all the data I am looking for.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. setting a file position pointer
    By JayCee++ in forum C++ Programming
    Replies: 3
    Last Post: 11-20-2011, 06:40 AM
  2. setting cursor position
    By scrasnu in forum C Programming
    Replies: 1
    Last Post: 10-04-2008, 10:28 AM
  3. Getting and setting cursor position
    By Spartan552 in forum Linux Programming
    Replies: 8
    Last Post: 01-14-2008, 05:27 AM
  4. How to keep track of the position in a binary file.
    By earth_angel in forum C Programming
    Replies: 4
    Last Post: 07-25-2005, 06:29 AM
  5. setting Cursor Position in C???
    By librab103 in forum C Programming
    Replies: 2
    Last Post: 07-26-2003, 02:54 PM

Tags for this Thread