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

如何在文件中查找Matroska Segment EBML字节序列?我的方法是否有误?

你的代码存在多个关键问题,导致无法匹配目标字节序列

咱们一步步拆解问题所在,再给出正确的实现方式:

核心错误点

  • 目标序列完全不匹配:你要找的是十六进制 0x18 0x53 0x80 0x67(对应十进制24、83、128、103),但代码里的判断条件是检查buffer[0]==1、buffer[1]==8等,这和目标序列完全无关,相当于在找另一个完全不同的字节串,肯定找不到结果。
  • 数组越界访问:你定义的buffer是char[8],数组索引从0开始,最大只能访问buffer[7],但代码里用到了buffer[8],这会触发未定义行为,程序可能崩溃或输出错误结果。
  • 读取逻辑错误:每次循环只读取1个字节到buffer[0],然后去检查buffer[1]到buffer[8]的内容——这些位置根本没有被新读取的数据填充,都是数组初始化后的垃圾值,自然不可能匹配成功。
  • 循环边界问题:当i接近文件末尾时,剩余字节不足4个,此时强行检查后续字节会导致读取超出文件范围,同样引发未定义行为。

正确的实现思路

要查找连续的4字节序列,推荐用滑动窗口的方式:逐个读取字节,维护最近的3个字节,每次新读一个字节后,就把这4个字节(前3个+当前)和目标序列对比。或者一次性读取整个文件到缓冲区,然后在缓冲区里查找(适合小文件)。

修正后的代码示例(滑动窗口方式)

#include <iostream>
#include <fstream>

int main() {
    std::ifstream is("your_file_path", std::ios::binary);
    if (!is.is_open()) {
        std::cerr << "Failed to open file!" << std::endl;
        return 1;
    }

    // 目标字节序列:0x18, 0x53, 0x80, 0x67
    const unsigned char target[] = {0x18, 0x53, 0x80, 0x67};
    const int target_len = sizeof(target) / sizeof(target[0]);

    // 滑动窗口缓冲区,保存最近的target_len-1个字节
    unsigned char window[target_len - 1] = {0};
    unsigned char current_byte;
    int bytes_read = 0;

    // 先读取前3个字节填充窗口
    while (bytes_read < target_len - 1 && is.read(reinterpret_cast<char*>(&current_byte), 1)) {
        window[bytes_read] = current_byte;
        bytes_read++;
    }

    // 开始滑动匹配
    while (is.read(reinterpret_cast<char*>(&current_byte), 1)) {
        // 检查当前窗口+当前字节是否匹配目标
        bool match = true;
        for (int i = 0; i < target_len - 1; i++) {
            if (window[i] != target[i]) {
                match = false;
                break;
            }
        }
        if (match && current_byte == target[target_len - 1]) {
            std::cout << "Found Matroska Segment EBML ID at position: " << is.tellg() - target_len << std::endl;
            // 可以选择继续查找或退出
            // break;
        }

        // 滑动窗口:把窗口内的字节往前移一位,放入当前字节
        for (int i = 0; i < target_len - 2; i++) {
            window[i] = window[i + 1];
        }
        window[target_len - 2] = current_byte;
    }

    is.close();
    return 0;
}

代码说明

  1. 明确目标字节序列为0x18, 0x53, 0x80, 0x67,直接用十六进制定义更清晰。
  2. 用滑动窗口保存最近的3个字节,每次读取新字节后,组合成4字节序列和目标对比,避免重复读取和越界。
  3. 处理文件打开失败的情况,增加鲁棒性。
  4. 匹配成功时输出位置(tellg()返回当前读取位置,减去目标长度就是序列起始位置)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.06 17:32:45