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

C++追加写入JSON文件时如何删除倒数第二行的]保证格式合法

C++ 追加写入合法JSON文件的实现方案

靠文件追加模式、手动删除倒数第二行]的写法容错率极低,只要文件末尾多了空行、空格,定位逻辑就会失效,最终输出格式错误的JSON。下面是两种稳定可落地的实现方案,完全不需要依赖不可靠的行号定位:

方案1:中小数据量场景(单文件大小<100MB)

这是最不容易出错的实现,逻辑非常简单:

  • 初始化时如果文件不存在,直接写入合法的基础JSON结构
  • 每次写入新数据前,把整个文件的内容完整读入内存
  • 在内存中完成字符串拼接:定位到数组末尾的],截断后插入新的条目内容,再补全闭合的括号
  • 把拼接完成的完整内容覆盖写回原文件

这种写法完全不需要处理复杂的文件流随机读写,哪怕文件末尾有多余空白字符也能正常处理,给你一份可直接运行的参考代码:

#include <fstream>
#include <string>
#include <sstream>
#include <cctype>

struct IOEntry {
    int tag;
    int disp;
    std::string mnemonic;
    bool iotype;
};

// 对应你原来的makefile()初始化逻辑
void initJsonFile() {
    std::ifstream checkFile("data.json");
    if (!checkFile.good()) {
        std::ofstream outFile("data.json");
        outFile << R"({
    "IO Inputs": []
})";
        outFile.close();
    }
    checkFile.close();
}

// 对应你原来的write()写入逻辑
void writeEntry(const IOEntry& entry) {
    initJsonFile();
    // 读入全量文件内容
    std::ifstream inFile("data.json");
    std::stringstream buffer;
    buffer << inFile.rdbuf();
    std::string content = buffer.str();
    inFile.close();

    // 定位数组结束符]的位置
    size_t arrEndPos = content.find_last_of(']');
    if (arrEndPos == std::string::npos) {
        // 文件格式损坏,重置为初始结构
        std::remove("data.json");
        initJsonFile();
        return;
    }

    // 判断数组是否为空,空数组不需要加前置逗号
    bool isEmptyArray = true;
    for (size_t i = arrEndPos - 1; i > 0; --i) {
        if (content[i] == '[') break;
        if (!isspace(static_cast<unsigned char>(content[i]))) {
            isEmptyArray = false;
            break;
        }
    }

    // 截断到]之前的位置,拼接新条目
    content.erase(arrEndPos);
    if (!isEmptyArray) {
        content += ",\n";
    }
    content += "    {\n";
    content += "        \"tag\": " + std::to_string(entry.tag) + ",\n";
    content += "        \"disp\": " + std::to_string(entry.disp) + ",\n";
    content += "        \"mnemonic\": \"" + entry.mnemonic + "\",\n";
    content += "        \"iotype\": " + (entry.iotype ? "true" : "false") + "\n";
    content += "    }\n";
    // 补全闭合括号
    content += "]\n}";

    // 全量覆盖写回
    std::ofstream outFile("data.json");
    outFile << content;
    outFile.close();
}

注意:手动拼接JSON字符串时,一定要对用户输入内容中的双引号、反斜杠、换行符等特殊字符做转义处理,否则依然可能出现格式错误。

方案2:大数据量场景(单文件大小>100MB,不适合全量读入内存)

如果数据量太大,全量读写的性能无法接受,可以直接操作文件流的读写指针定位,核心逻辑是不要按行找],而是从文件末尾往前逐字符跳过所有空白字符,定位到最后一个非空白的]字符,把写指针移到这个位置直接覆盖即可,核心定位代码片段如下:

#include <fstream>
#include <cctype>

// 打开文件支持同时读写
std::fstream file("data.json", std::ios::in | std::ios::out);
file.seekg(0, std::ios::end);
long long fileSize = file.tellg();
long long bracketPos = -1;
char curChar;

// 从文件末尾往前遍历,找第一个非空白字符
for (long long i = fileSize - 1; i >= 0; --i) {
    file.seekg(i);
    file.get(curChar);
    if (!isspace(static_cast<unsigned char>(curChar))) {
        if (curChar == ']') {
            bracketPos = i;
        }
        break;
    }
}

if (bracketPos == -1) {
    // 此处处理文件格式损坏的情况
    file.close();
    return;
}

// 将写指针移到]的位置,后续写入新条目后补全]\n}即可
file.seekp(bracketPos);
// 此处追加逗号、新条目内容,最后写入闭合括号
// ... 你的写入逻辑
file.close();

实用建议:如果是正式项目使用,不要手动拼接JSON,直接接入成熟的JSON序列化库即可,库会自动处理格式校验、特殊字符转义、结构闭合等问题,能避免90%以上的JSON格式错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 10:39:19