Thread: Working with binary files

  1. #1
    Registered User
    Join Date
    Mar 2020
    Posts
    15

    Working with binary files

    Hello,

    I've got an assignment to write a program that keeps track of a library (small one, nothing too great or polished) and to be saved as binary. I have a struct for members, and entering / printing one works perfectly. We have been told to write, at the beginning of the file, number of members. So, when entering 1st, it should be 1, appending 2nd 2, appending 3rd 3, etc. Problem is, I don't know how to write and then get a single int from the beginning of the file to use it in loop when printing more than 1 member. Any help?

    Thank you, 574515.

  2. #2
    Registered User
    Join Date
    Feb 2019
    Posts
    676
    fwrite() doesn't work for you?

  3. #3
    Registered User
    Join Date
    Mar 2020
    Posts
    15
    Hello,

    thank you for your resposne. Fwrite() for me writes (and fread() reads) something random (like 8k+ something or -8k something).

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,056
    It's better to post actual code than saying "I tried x and something happened".
    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.

  5. #5
    Registered User
    Join Date
    Mar 2020
    Posts
    15
    This is checking if file exists, if not, creating and writing 1 (as in 1st member) at the beginning (or so I thought).

    Code:
    int x = 1;
        FILE* open_F = NULL;
        open_F = fopen("myfile.bin", "rb");
        if (open_F == NULL) {
            open_F = fopen("myfile.bin", "wb");
            if (open_F == NULL) {
                perror("File error");
            }
            MEMBER* member = NULL;
            member = (MEMBER*)calloc(1, sizeof(MEMBER));
            if (member == NULL) {
                perror("Struct error");
            }
            /*entering members in struct*/
            rewind(open_F);
            fwrite(&x, sizeof(int), 1, open_F);
            fwrite(&member, sizeof(MEMBER), 1, open_F);
            fclose(open_F);
            free(member);
    }
    This is for reading / printing members:

    Code:
    FILE* open_F = NULL;
        open_F = fopen("myfile.bin", "rb");
        if (open_F == NULL) {
            perror("File error");
        }
        else{
            int x;
            rewind(open_F);
            fread(&x, sizeof(int), 1, open_F);
            MEMBER* member = NULL;
            member = (MEMBER*)calloc(x, sizeof(MEMBER));
            if (member == NULL) {
                perror("Struct error");
            }
            fread(&member, sizeof(MEMBER), x, open_F);
            for(int i = 0; i < x; i++){
                /*printing out members/*
            }    
            fclose(open_F);
            free(member);
    }
    Last edited by 574515; 04-28-2020 at 10:35 AM.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,056
    Member is a pointer, so

    fwrite(member, sizeof(MEMBER), 1, open_F);

    fread(member, sizeof(MEMBER), x, open_F);
    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
    Mar 2020
    Posts
    15
    Thank you, I've corrected that, but my original error still persists. I need to write a number of members in a file, overall number, not 1st, 2nd etc. If file doesn't exist I need to make a new file and put 1 at the beginning of file, if it exists then with every append (add new member) I need to increase that number (adding 1 by 1 now until I get whole logic behind that).

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,056
    To read it
    Code:
            rewind(open_F);
            fread(&x, sizeof(int), 1, open_F);
    To write it, and append a new record to the end of the file
    Code:
            rewind(open_F);
            fwrite(&x, sizeof(int), 1, open_F);
            fseek(open_F, 0, SEEK_END);
            fwrite(member, sizeof(MEMBER), 1, open_F);
            fflush(open_F);

    You only need the fflush() if you're keeping the file open for further reading.
    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.

  9. #9
    Registered User
    Join Date
    Mar 2020
    Posts
    15
    Quote Originally Posted by Salem View Post
    To read it
    Code:
            rewind(open_F);
            fread(&x, sizeof(int), 1, open_F);
    To write it, and append a new record to the end of the file
    Code:
            rewind(open_F);
            fwrite(&x, sizeof(int), 1, open_F);
            fseek(open_F, 0, SEEK_END);
            fwrite(member, sizeof(MEMBER), 1, open_F);
            fflush(open_F);

    You only need the fflush() if you're keeping the file open for further reading.
    Thank you for your help! I've done that and now I get error "stream.valid()" when trying to read. Read code:

    Code:
    FILE* open_F = NULL;open_F = fopen("myfile.bin", "rb");
    if (open_F == NULL) {
        perror("File error");
    }
    else {
        int x, i;
        rewind(open_F);
        fread(&x, sizeof(int), 1, open_F);
        MEMBER* member = NULL;
        member = (MEMBER*)calloc(x, sizeof(MEMBER));
        if (member == NULL) {
            perror("Struct error");
        }
        fread(&member, sizeof(MEMBER), x, open_F);
        for (i = 0; i < x; i++) {
            /*printing members
            e.g. fprintf(stdout, "Name: %s", (member + i)->name);*/
        }
        fclose(open_F);
        free(member);
    }
    EDIT: Plus, "counter" is not working, no matter how many members I enter, always shows "1", even tho when I open my *.bin file in VS it shows proper values.
    Last edited by 574515; 04-28-2020 at 02:45 PM.

  10. #10
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,776
    It seems to me that you could do with more stringent error checking, e.g.,
    Code:
    FILE *open_F = fopen("myfile.bin", "rb");
    if (!open_F) {
        perror("fopen() failed to open the file");
        return;
    }
    
    int num_records;
    if (fread(&num_records, sizeof(num_records), 1, open_F) != 1) {
        perror("fread() failed to read the number of records");
        fclose(open_F);
        return;
    }
    
    MEMBER *members = calloc(num_records, sizeof(*members));
    if (!members) {
        perror("calloc() failed to allocate space for the records");
        fclose(open_F);
        return;
    }
    
    if (fread(&members, sizeof(*members), num_records, open_F) != num_records) {
        perror("fread() failed to read the records");
        free(members);
        fclose(open_F);
        return;
    }
    fclose(open_F);
    
    for (int i = 0; i < num_records; ++i) {
        printf("Name: %s\n", members[i].name);
    }
    free(members);
    One thing that you have not shown: what is the layout of the MEMBER struct? In particular, does it contain a pointer member or a member of struct type that does contain a pointer member?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  11. #11
    Registered User
    Join Date
    Mar 2020
    Posts
    15
    Thank you for your answer! I will try to do that. My struct has 4 char arrays (array1[20]...) and 1 int, no pointers or anything.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,056
    > Thank you for your help! I've done that and now I get error "stream.valid()" when trying to read. Read code:
    ...
    > fread(&member, sizeof(MEMBER), x, open_F);
    Yes, and you're still passing the addresses of pointers.

    I thought you understood that point from previous.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. binary files: copying jpeg or video files
    By cfanatic in forum C Programming
    Replies: 5
    Last Post: 07-19-2012, 08:17 AM
  2. How can a binary get its working dir at run-time?
    By meili100 in forum C++ Programming
    Replies: 16
    Last Post: 04-09-2008, 05:48 PM
  3. Binary Conversion not working...
    By Junior89 in forum C++ Programming
    Replies: 3
    Last Post: 09-11-2007, 12:05 PM
  4. working with binary files
    By spank in forum C Programming
    Replies: 21
    Last Post: 01-04-2006, 08:55 AM
  5. Working with Binary Numbers in C++
    By goron350 in forum C++ Programming
    Replies: 18
    Last Post: 07-24-2005, 05:03 PM

Tags for this Thread