写入结构体到二进制文件后后续结构体丢失问题求助
解决二进制文件写入结构体后后续数据丢失的问题
我帮你排查了代码里的几个关键错误,这就是导致目标结构体之后的数据消失的原因:
问题根源拆解
1. 读取位置计算错误
你在读取玩家数据的循环里用了readstream.seekg(i, ios::beg),这里的偏移量应该是i * sizeof(player)才对。每个player是int类型(占4字节左右),直接用i当偏移量,会导致每次读取的位置都不对,比如第2个玩家你只偏移1字节,根本没定位到正确的结构体位置。
2. 循环里过早关闭文件流
你在第一次读取完一个玩家后就调用了readstream.close(),这直接把文件流关了!后面的循环根本读不到任何数据,playerTable里除了第一个元素,剩下的都是未初始化的垃圾值。
3. 写回文件时的覆盖问题
当你把playerTable写回文件时,因为数组里大部分是垃圾数据,再加上如果用了ios::out模式(默认会截断原文件),原文件里后续的有效结构体就被这些垃圾数据覆盖了,看起来就像是“消失”了。
修正后的完整代码
#include <fstream> using namespace std; struct player{ int UUID; }; // 更新玩家数据库中的玩家信息 bool savePlayer(player playerData){ int count = 0; // 统计文件中的玩家数量 fstream countstream("player.bin", ios::binary | ios::in); if(countstream.is_open()){ countstream.seekg(0, ios::end); // 处理文件为空的情况,避免除以0 if(countstream.tellg() != 0){ count = countstream.tellg() / sizeof(player); } countstream.close(); } bool found = false; player* playerTable = nullptr; // 读取现有玩家数据 if(count > 0){ // 用动态数组,避免栈溢出(玩家多了栈顶会爆) playerTable = new player[count]; fstream readstream("player.bin", ios::binary | ios::in); if(readstream.is_open()){ // 一次性读取所有数据,比循环读高效还不容易错 readstream.read(reinterpret_cast<char*>(playerTable), count * sizeof(player)); readstream.close(); } // 查找并更新目标玩家 for(int i = 0; i < count; i++){ if(playerTable[i].UUID == playerData.UUID){ found = true; playerTable[i] = playerData; break; // 找到就停,不用白跑循环 } } } // 如果没找到,新增玩家 if(!found){ player* newTable = new player[count + 1]; // 复制原有数据 if(count > 0){ for(int i = 0; i < count; i++){ newTable[i] = playerTable[i]; } delete[] playerTable; } newTable[count] = playerData; playerTable = newTable; count++; } // 把完整数据写回文件 fstream writestream("player.bin", ios::binary | ios::out | ios::trunc); if(writestream.is_open()){ writestream.write(reinterpret_cast<char*>(playerTable), count * sizeof(player)); writestream.close(); } // 记得释放动态内存,别内存泄漏 delete[] playerTable; return true; }
关键优化点说明
- 改用一次性读取所有数据,避免手动计算偏移量的错误,代码也更简洁高效。
- 把文件流的关闭移到循环外面,确保所有数据都读完再关流。
- 用动态数组替代栈数组,栈的空间有限,玩家多了会直接栈溢出崩溃。
- 补充了新增玩家的逻辑,原代码只处理了更新的情况。
- 明确用
ios::trunc截断原文件后写入完整数据,保证文件内容和内存中的数组完全一致。
内容的提问来源于stack exchange,提问作者SpeedrunnerG55




