You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++程序无法将修改内容写入.dat文件问题求助

C++二进制文件编辑后数据未保存问题

问题描述

我编写C++程序时遇到一个问题:程序能打开文件,让用户选择并读取一条记录,输入新信息后尝试保存,但重新运行程序时,修改的内容并未保存。已排查过.dat文件的创建逻辑,确认不是该环节的问题。

相关代码

编辑记录的程序代码

//This program allows the user to edit a specific
//record in the inventory file
#include <iostream>
#include <fstream>
using namespace std;

const int DESC_SIZE = 31;
//Declaration of Invtry structure
struct Invtry{
    char desc[DESC_SIZE];
    int qty;
    double wholesaleCost;
    double retailCost;
    int dateDay;
    int dateMonth;
    int dateYear;
};

int main(){
    //Variables needed to read the file
    Invtry record;
    long recNum;

    //Open the file
    fstream inventory("invtry.dat", ios::in | ios::out | ios::binary);
    if (!inventory){
        cout << "Error opening file";
        return 0;
    }

    //Move to the desired record and read it into record
    cout << "Which record do you want to edit?";
    cin >> recNum;
    inventory.seekg(recNum * sizeof(record), ios::beg);
    inventory.read(reinterpret_cast<char *>(&record), sizeof(record));

    //Get new data from user and edit in-memory record
    cout << "Description: ";
    cout << record.desc << endl;
    cout << "Quantity: ";
    cout << record.qty << endl;
    cout << "Wholesale Cost: ";
    cout << record.wholesaleCost << endl;
    cout << "Retail Cost: ";
    cout << record.retailCost << endl;
    cout << "Date Added: ";
    cout << record.dateMonth << "/" << record.dateDay << "/" << record.dateYear << endl;
    cout << "Enter the new data:\n";
    cout << "Description: ";
    cin.ignore();
    cin.getline(record.desc, DESC_SIZE);
    cout << "Quantity: ";
    cin >> record.qty;
    cout << "Wholesale Cost: ";
    cin >> record.wholesaleCost;
    cout << "Retail Cost: ";
    cin >> record.retailCost;
    cout << "Date: Month: ";
    cin >> record.dateMonth;
    cout << "Date: Day: ";
    cin >> record.dateDay;
    cout << "Date: Year: ";
    cin >> record.dateYear;

    //Move to the right place in file and write the record
    inventory.seekp(recNum * sizeof(record), ios::beg);
    inventory.write(reinterpret_cast<char *>(&record),sizeof(record));

    //Close the file
    inventory.close();
    return 0;
}

创建.dat文件的程序代码

//This program sets up a file of blank inventory records
#include <iostream>
#include <fstream>
using namespace std;

const int DESC_SIZE = 31, NUM_RECORDS = 5;
//Declaration of Invtry structure
struct Invtry{
    char desc[DESC_SIZE];
    int qty;
    double wholesaleCost;
    double retailCost;
    int dateDay;
    int dateMonth;
    int dateYear;
};

int main(){
    //Variables needed to write the file
    Invtry record = {"",0,0.0,0.0,0,0,0};

    //Create file object and open file
    fstream inventory("invtry.dat", ios::out | ios::binary);
    if (!inventory){
        cout << "Error opening file.";
        return 0;
    }

    //Now write the blank records
    for (int count = 0; count < NUM_RECORDS; count ++){
        cout << "Now writing record " << count << endl;
        inventory.write(reinterpret_cast<char *>(&record),sizeof(record));
    }
    //close the file
    inventory.close();
    return 0;
}

问题原因与解决方案

核心问题

当使用fstream同时进行读写操作时,若读取操作后触发了文件结束标志(eofbit)(比如读取最后一条记录时),后续的写入操作会因文件流处于错误状态而失败,导致数据无法保存到磁盘。此外,部分编译器实现中,读写指针共享的情况下,切换操作时未正确重置指针状态也会引发问题。

修复步骤

在写入记录前,添加代码清除文件流的错误状态,并确保写入操作的正确性:

  1. 在inventory.seekp(...)之前,调用inventory.clear()清除所有错误标志:
// 清除文件流错误状态,确保写入操作正常执行
inventory.clear();
//Move to the right place in file and write the record
inventory.seekp(recNum * sizeof(record), ios::beg);
inventory.write(reinterpret_cast<char *>(&record),sizeof(record));
  1. 可选:写入后调用inventory.flush()强制将缓存数据写入磁盘(虽然close()会自动执行此操作,但显式调用可避免缓存未及时同步的问题):
inventory.write(reinterpret_cast<char *>(&record),sizeof(record));
inventory.flush(); // 强制写入磁盘

修复后的关键代码片段

//Get new data from user and edit in-memory record
// ...(用户输入代码保持不变)

// 清除错误状态,确保写入正常执行
inventory.clear();
//Move to the right place in file and write the record
inventory.seekp(recNum * sizeof(record), ios::beg);
inventory.write(reinterpret_cast<char *>(&record),sizeof(record));
inventory.flush();

//Close the file
inventory.close();

内容的提问来源于stack exchange,提问作者Daniel Lippold

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 16:48:06