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

使用Boost Zstd过滤流读取压缩日志文件新增内容遇问题

Boost Zstd过滤流无法实时读取新增压缩日志内容的解决方案

我正在开发C++程序,用Boost 1.83的Zstd过滤流追踪磁盘上的实时Zstd压缩日志,但过滤流无法识别文件新增内容。代码如下:

#include <iostream>
#include <string>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/zlib.hpp> // Example filter (can be replaced with any filter)
#include <fstream>
#include <zstd.h>

namespace io = boost::iostreams;

int main() {
    // Create a filtering_istreambuf with a zlib decompressor
    io::filtering_streambuf<io::input> in;
    in.push(io::zstd_decompressor());
    std::ifstream file("compressed_file.txt.zst", std::ios_base::in | std::ios_base::binary);
    in.push(file);
    // Construct an istream from the underlying streambuf
    std::istream inputStream(&in);
    // Read lines from the input stream using std::getline()

    while (true) {

        std::string line;
        while (std::getline(inputStream, line)) {
            std::cout << "Line: " << line << std::endl;
        }

        if (inputStream.eof()) {
            inputStream.clear();
        }
    }
    
    return 0;
}

问题根源

  1. std::ifstream不会主动检测文件长度变化,读到EOF后即使文件新增内容,也不会自动触发重新读取。
  2. Boost过滤流存在内部缓冲,文件新增内容可能被缓冲机制屏蔽,无法被上层流感知。
  3. 如果日志不是以Zstd多帧格式追加,解压流无法识别后续非完整帧的压缩数据。

解决方案

方案1:定期检查文件变化并重置流

通过定期检查文件大小,判断是否有新增内容,然后重置文件流和过滤流状态,实现实时读取:

#include <iostream>
#include <string>
#include <boost/iostreams/filtering_streambuf.hpp>
#include <boost/iostreams/filter/zstd.hpp>
#include <fstream>
#include <chrono>
#include <thread>

namespace io = boost::iostreams;

int main() {
    std::ifstream file("compressed_file.txt.zst", std::ios_base::in | std::ios_base::binary);
    if (!file.is_open()) {
        std::cerr << "Failed to open file" << std::endl;
        return 1;
    }

    io::filtering_streambuf<io::input> in;
    in.push(io::zstd_decompressor());
    in.push(file);
    std::istream inputStream(&in);

    std::streampos last_pos = file.tellg();
    while (true) {
        // 检查文件是否有新增内容
        file.seekg(0, std::ios::end);
        std::streampos current_size = file.tellg();
        
        if (current_size > last_pos) {
            // 回到上次读取的位置
            file.seekg(last_pos);
            // 重置过滤流,清除之前的EOF状态和缓冲
            in.pop();
            in.push(file);
            inputStream.clear();

            // 读取新增内容
            std::string line;
            while (std::getline(inputStream, line)) {
                std::cout << "Line: " << line << std::endl;
            }
            last_pos = file.tellg();
        }

        // 每秒检查一次,可根据需求调整间隔
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    return 0;
}

方案2:禁用过滤流内部缓冲

关闭Boost过滤流的缓冲机制,让数据直接从文件流读取,减少缓冲带来的延迟:

修改过滤流初始化部分:

io::filtering_streambuf<io::input> in;
// 禁用过滤流和文件流的缓冲
in.push(io::zstd_decompressor(), io::no_buffer);
in.push(file, io::no_buffer);
std::istream inputStream(&in);

注意:禁用缓冲会降低读取性能,适合实时性优先的场景。

方案3:确保日志以Zstd多帧格式追加

如果日志写入端是单帧压缩后直接追加,解压流无法识别后续非完整帧数据。需要让写入端每次追加新的Zstd帧:

写入端核心逻辑示例:

#include <fstream>
#include <zstd.h>

void append_log_to_zstd(const std::string& log_content, const std::string& file_path) {
    std::ofstream file(file_path, std::ios_base::out | std::ios_base::binary | std::ios_base::app);
    if (!file.is_open()) return;

    ZSTD_CCtx* cctx = ZSTD_createCCtx();
    if (!cctx) return;

    // 压缩日志内容为独立Zstd帧
    ZSTD_inBuffer in_buf = {log_content.data(), log_content.size(), 0};
    ZSTD_outBuffer out_buf;
    char out_buffer[ZSTD_CStreamOutSize()];
    
    while (in_buf.pos < in_buf.size) {
        out_buf = {out_buffer, sizeof(out_buffer), 0};
        size_t ret = ZSTD_compressStream(cctx, &out_buf, &in_buf);
        if (ZSTD_isError(ret)) break;
        file.write(out_buffer, out_buf.pos);
    }

    // 结束当前帧
    ZSTD_outBuffer end_buf = {out_buffer, sizeof(out_buffer), 0};
    size_t ret = ZSTD_endStream(cctx, &end_buf);
    if (!ZSTD_isError(ret)) {
        file.write(out_buffer, end_buf.pos);
    }

    ZSTD_freeCCtx(cctx);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 01:42:22