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

C++如何不转字符串即可裁剪istream输入流末尾的无效内容?

流模式下裁剪JSON末尾无效内容的实现方法

你已经定位到了顶层JSON对象的起始{,后续只要维护大括号配对计数、字符串和转义状态,读到配对的顶层}时直接截断流即可,全程不需要将JSON整体转为字符串,内存占用极低。

具体实现方案

方案1:自定义过滤流包装(适配支持流输入的反序列化器)

通过继承std::streambuf实现一个过滤缓冲层,包裹原有的std::ifstream,在读取逻辑中加入状态判断,自动在JSON结束位置返回EOF,反序列化器感知不到底层逻辑差异,直接传入包装后的流即可。
示例代码:

#include <streambuf>
#include <istream>
#include <fstream>
#include <limits>

class JsonTrimStreambuf : public std::streambuf {
private:
    std::streambuf* underlying;
    int brace_count = 1; // 已经定位到起始{,初始层数为1
    bool in_string = false;
    bool is_escaped = false;
    char buf; // 单字符缓冲,无额外内存开销

protected:
    int underflow() override {
        if (brace_count == 0) {
            return traits_type::eof();
        }
        int ch = underlying->sbumpc();
        if (ch == traits_type::eof()) {
            return traits_type::eof();
        }

        if (is_escaped) {
            is_escaped = false;
        } else if (ch == '\\' && in_string) {
            is_escaped = true;
        } else if (ch == '"') {
            in_string = !in_string;
        } else if (!in_string) {
            if (ch == '{') {
                brace_count++;
            } else if (ch == '}') {
                brace_count--;
            }
        }

        buf = traits_type::to_char_type(ch);
        setg(&buf, &buf, &buf + 1);
        return ch;
    }

public:
    explicit JsonTrimStreambuf(std::streambuf* buf) : underlying(buf) {}
};

// 使用示例
int main() {
    std::ifstream myIfstream("your_file.txt");
    // 原有裁剪开头无效内容的逻辑
    myIfstream.ignore(std::numeric_limits<std::streamsize>::max(), '{');
    myIfstream.unget();

    // 构造过滤流
    JsonTrimStreambuf trim_buf(myIfstream.rdbuf());
    std::istream json_in(&trim_buf);

    // 直接把json_in传给你的JSON反序列化器即可,会自动在JSON结束位置停止
    // 例如:auto json_obj = nlohmann::json::parse(json_in);
    return 0;
}

方案2:逐字符喂入反序列化器(适配支持逐字符输入的反序列化器)

如果你的反序列化器提供逐字符处理的接口,可以不用自定义流,直接在读取字符时维护上述状态,直到顶层}出现后停止喂入即可:

// 假设反序列化器有类似feed(char ch)的逐字符输入接口
int brace_count = 1;
bool in_string = false;
bool is_escaped = false;
char ch;
while (myIfstream.get(ch)) {
    if (is_escaped) {
        is_escaped = false;
    } else if (ch == '\\' && in_string) {
        is_escaped = true;
    } else if (ch == '"') {
        in_string = !in_string;
    } else if (!in_string) {
        if (ch == '{') {
            brace_count++;
        } else if (ch == '}') {
            brace_count--;
        }
    }

    // 喂入字符给反序列化器
    deserializer.feed(ch);

    if (brace_count == 0) {
        break;
    }
}
// 调用反序列化器结束处理的接口即可

注意事项

  • 如果你的JSON顶层结构是数组而非对象,可以把逻辑中的{/}替换为[/],适配数组结构的配对
  • 该方案默认输入中的JSON是语法合法的,如果存在语法错误可能提前截断或者计数异常,可以根据需求加入错误处理逻辑

内容的提问来源于stack exchange,提问作者Le Canard fou

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 11:45:01