-1

Whenever I write a struct to a binary file, any structs after it go away, although any structs written before it remain.

I'm opening the file stream in binary output mode and my structs contain only primitive datatypes.

I also made sure to make separate file streams for each operation.

Output:

create players
765
51

save 1
765

save 2
765
51

** struct definition**

struct player{
    int UUID;
};

Function saving the structs

//updates player information in the player database
bool savePlayer(player playerData){
    //count how manny playrs are in file
    // Create our objects.
    fstream countstream;
    int count = 0;
    countstream.open ("player.bin", ios::binary | ios::in);
    if(countstream.is_open()){
        countstream.seekg(0, ios::end); //set position to end
        count = countstream.tellg()/sizeof(player);
        //retuns number of players in file by getting
        //the index of the position and dividing it by the size of each player
        //no loops required :D
    }
    countstream.close();

    bool found = false;

    //if file is not empty,look through it
    if(count > 0){
        player playerTable[count];
        fstream readstream;
        readstream.open ("player.bin", ios::binary | ios::in);
        //build table
        for(int i = 0; i < count; i++){
            readstream.seekg(i, ios::beg); //set position to end
            readstream.read(reinterpret_cast <char *> (&playerTable[i]), 
                            sizeof(player));
            readstream.close();
        }

        //check table
        for(int i = 0; i < count; i++){
            if(playerTable[i].UUID == playerData.UUID){
                found = true;
                playerTable[i] = playerData;
            }
        }

        //write table back to file
        if(found){
            fstream writestream; //create writestream
            writestream.open ("player.bin", ios::binary | ios::out);
            for(int i = 0; i < count; i++){
                writestream.seekg(i, ios::beg); //set position to player
                writestream.write(reinterpret_cast <char *> (&playerTable[i]), 
                                  sizeof(player));
                if(!writestream.fail()){
                    writestream.close();
                    return true;
                }
                else{
                    writestream.close();
                    return false;
                }
                readstream.close();
            }
        }
    }

    //append if not found
    if(!found){
        fstream appendstream;
        appendstream.open ("player.bin", ios::binary | ios::out | 
                           ios::app);
        appendstream.write(reinterpret_cast <char *> (&playerData), 
                           sizeof(player));
        appendstream.close();
        if(!appendstream.fail()){
            appendstream.close();
            return true;
        }
        else{
            appendstream.close();

            return false;
        }
    }
    return false;
}

Any suggestions will be appreciated.

SU3
  • 5,064
  • 3
  • 35
  • 66
  • 2
    in the `readstream` loop you close the file inside the loop , so you only read one line – M.M Mar 23 '18 at 03:20
  • *my structs contain only primitive datatypes* -- Seeing is believing. Please post `player`. – PaulMcKenzie Mar 23 '18 at 03:21
  • Just an FYI: even if you solve all the above issues, this will only work for with an OS and compiler with the same type-sizes and byte-order as it was originally written on. You should really use a lightweight tool like USCILab's Cereal to serialize structs for you: https://github.com/USCiLab/cereal – Alex Huszagh Mar 23 '18 at 03:23
  • Why do you use `seekg()` in the `readstream` loop? If you're going to seek, you should be doing it by multiples of `sizeof *playerTable`. – Barmar Mar 23 '18 at 03:23
  • @SpeedrunnerG55 -- Put that info in the question, not as a comment. – PaulMcKenzie Mar 23 '18 at 03:27
  • I removed the close statement from the read stream loop, it still does the same thing. although I do recognize that should have been outside the loop. – SpeedrunnerG55 Mar 23 '18 at 03:27
  • 1
    There's also no need to get the count first. Just use `while (readstream.read(...))` to keep reading until you get to the end. – Barmar Mar 23 '18 at 03:27
  • 1
    it should be `readstream.seekg(i * sizeof(player), ios::beg);`. But you shouldn't need to seek at all, each `read()` starts from where the previous one finished. – Barmar Mar 23 '18 at 03:29
  • I removed the if statement at the end of the write stream loop and it works as intended, but is there a way I could tell if the write stream fails? – SpeedrunnerG55 Mar 23 '18 at 03:37
  • after some investigation, I found the players are being deleted when I open the write stream to save the new player. not even during the write cycle but right at the point of opening the file, like its in trunc mode but its not. its just ios::binary and ios::out – SpeedrunnerG55 Mar 23 '18 at 15:20

1 Answers1

-1

You're making this much harder than necessary. You don't need to read all the data into an array. You can read each item into a variable, and check if it's the one you want to replace. And by opening the file in both read and write mode, you can simply overwrite that entry in the file while reading it.

bool savePlayer(player playerData){

    player curPlayer;
    fstream stream;
    stream.open ("player.bin", ios::binary | ios::in | ios::out);
    while(stream.read(reinterpret_cast<char*>(&curPlayer), sizeof(curPlayer))){
        if (curPlayer.UUID == playerData.UUID) {
            stream.seekg(-(sizeof curPlayer), ios::cur); // back up to location of current player
            break;
        }
    }
    stream.write(reinterpret_cast<char*>(&playerData), sizeof playerData);
    stream.close();
    return false;
}
SU3
  • 5,064
  • 3
  • 35
  • 66
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • it's not creating the file when it does not exist. I don't think I can use the same stream in both in and out modes. i know technically it should work but it just does not do anything when i try it – SpeedrunnerG55 Mar 23 '18 at 03:52
  • See https://stackoverflow.com/questions/23967697/if-file-exist-work-with-it-if-no-create-it – Barmar Mar 23 '18 at 03:55