C++如何在文件分配表十六进制转储文件中跨多行搜索字符串
我之前处理十六进制转储文件时也遇到过一模一样的问题——逐行读取确实会把跨两行的子串拆成两半,根本搜不到。下面给你几个针对性的解决方案,从简单到复杂都有:
方法1:一次性加载整个文件到内存搜索(适合小文件)
这是最直接的方案,把整个文件内容拼成一个无换行的大字符串,直接调用find()就能覆盖所有跨行情况,代码实现也最简单:
#include <fstream> #include <string> #include <iostream> #include <iterator> int main() { std::ifstream dump_file("fat_dump.txt"); if (!dump_file.is_open()) { std::cerr << "Failed to open the FAT dump file" << std::endl; return 1; } // 把整个文件读入一个字符串(自动忽略换行符的影响) std::string full_content((std::istreambuf_iterator<char>(dump_file)), std::istreambuf_iterator<char>()); // 替换成你要搜索的目标子串 std::string target_substr = "d36dd2eb8fc9f20780e936e9"; size_t found_pos = full_content.find(target_substr); if (found_pos != std::string::npos) { std::cout << "Found target at position: " << found_pos << std::endl; } else { std::cout << "Target substring not found" << std::endl; } return 0; }
注意:如果你的FAT转储文件特别大(比如几个GB),这种方法会占用过多内存,这时候就需要用下面的流式处理方案。
方法2:滑动窗口式流式读取(适合大文件)
核心思路是每次读取一块数据,保留上一块的末尾部分(长度等于目标子串长度-1),和当前块拼接后再搜索,这样就能覆盖跨块(也就是跨原文件行)的子串:
#include <fstream> #include <string> #include <iostream> int main() { const size_t BUFFER_SIZE = 4096; // 可根据内存情况调整 std::string target_substr = "d36dd2eb8fc9f20780e936e9"; size_t target_len = target_substr.size(); if (target_len == 0) { std::cerr << "Target substring cannot be empty" << std::endl; return 1; } std::ifstream dump_file("fat_dump.txt", std::ios::binary); if (!dump_file.is_open()) { std::cerr << "Failed to open the FAT dump file" << std::endl; return 1; } std::string leftover; // 保存上一块的末尾,用于拼接当前块 char temp_buffer[BUFFER_SIZE]; bool found = false; while (dump_file.read(temp_buffer, BUFFER_SIZE)) { std::string current_block(temp_buffer, dump_file.gcount()); // 拼接残留内容和当前块,确保跨块子串被包含 std::string search_block = leftover + current_block; size_t pos = search_block.find(target_substr); if (pos != std::string::npos) { // 计算在文件中的绝对位置 size_t total_read = dump_file.tellg() - current_block.size() - leftover.size(); std::cout << "Found target at position: " << total_read + pos << std::endl; found = true; break; } // 更新残留内容:保留当前块最后target_len-1个字符 if (current_block.size() >= target_len - 1) { leftover = current_block.substr(current_block.size() - (target_len - 1)); } else { leftover = current_block; } } // 处理文件最后一块的残留内容 if (!found) { std::string final_block(temp_buffer, dump_file.gcount()); std::string search_block = leftover + final_block; size_t pos = search_block.find(target_substr); if (pos != std::string::npos) { size_t total_read = dump_file.tellg() - final_block.size() - leftover.size(); std::cout << "Found target at position: " << total_read + pos << std::endl; } else { std::cout << "Target substring not found" << std::endl; } } return 0; }
额外提示:处理十六进制转储的空格问题
如果你的目标子串是原始二进制对应的纯十六进制串,转储文件中每行的空格会干扰搜索(比如跨块的5e和7f在文件中是5e 7f),可以在读取时先去掉所有空格:
// 以方法1为例,在读取文件后添加: full_content.erase(std::remove(full_content.begin(), full_content.end(), ' '), full_content.end());
这样就能搜索纯十六进制形式的目标串了。
内容的提问来源于stack exchange,提问作者MMMMMCK
相关产品推荐
相关产品推荐

