【问题标题】:How to find a string in a binary file?如何在二进制文件中查找字符串?
【发布时间】:2019-05-07 19:09:04
【问题描述】:

我想在二进制文件中查找特定字符串“fileSize”。
查找该字符串的目的是获取字符串旁边的 4 个字节,因为这 4 个字节包含我要读取的数据的大小。

二进制文件内容如下:

同一字符串在另一个位置:

另一个职位:

以下是将数据写入文件的函数:

void W_Data(char *readableFile, char *writableFile) {
    ifstream RFile(readableFile, ios::binary);
    ofstream WFile(writableFile, ios::binary | ios::app);

    RFile.seekg(0, ios::end);
    unsigned long size = (unsigned long)RFile.tellg();
    RFile.seekg(0, ios::beg);

    unsigned int bufferSize = 1024;
    char *contentsBuffer = new char[bufferSize];

    WFile.write("fileSize:", 9);
    WFile.write((char*)&size, sizeof(unsigned long));
    while (!RFile.eof()) {
        RFile.read(contentsBuffer, bufferSize);
        WFile.write(contentsBuffer, bufferSize); 
    }
    RFile.close();
    WFile.close();
    delete contentsBuffer;
    contentsBuffer = NULL;
}

还有,搜索字符串的函数:

void R_Data(char *readableFile) {
    ifstream RFile(readableFile, ios::binary);

    const unsigned int bufferSize = 9;

    char fileSize[bufferSize];
    while (RFile.read(fileSize, bufferSize)) {
        if (strcmp(fileSize, "fileSize:") == 0) {
            cout << "Exists" << endl;
        }
    }
    RFile.close();
}

如何在二进制文件中查找特定字符串?

【问题讨论】:

  • 如果你想将你的 char 数组与字符串文字进行比较,而不需要将任何内容转换为 std::string,则需要使用 strcmpfileSize == "fileSize:" 不会像你期望的那样工作。
  • 不确定实际的问题是什么。
  • 请注意,以 9 字节块读取文件然后进行比较假定字符串 "fileSize:" 在 9 字节边界上对齐。
  • 使用grep -a filesize
  • @scohe001:我用过if (strcmp(fileSize, "filesize:") == 0),但它并没有像我预期的那样工作。

标签: c++ file binary-data


【解决方案1】:

我认为使用find() 是一种搜索模式的简单方法。

void R_Data(const std::string filename, const std::string pattern) {
    std::ifstream(filename, std::ios::binary);
    char buffer[1024];

    while (file.read(buffer, 1024)) {
        std::string temp(buffer, 1024);
        std::size_t pos = 0, old = 0;

        while (pos != std::string::npos) {
            pos = temp.find(pattern, old);
            old = pos + pattern.length();
            if ( pos != std::string::npos )
                std::cout << "Exists" << std::endl;
        }
        file.seekg(pattern.length()-1, std::ios::cur);
    }
}

【讨论】:

  • 我认为 seekg 部分应该是 seekg(1-pattern.length(), std::ios::cur);假设我们尝试在'AAAA1234AAAA'中找到'1234',并且读取缓冲区大小为6。
【解决方案2】:

如何在二进制文件中查找特定字符串?

如果你不知道字符串在文件中的位置,我建议如下:

  1. 查找文件的大小。
  2. 分配内存以便能够读取文件中的所有内容。
  3. 读取从文件到分配内存的所有内容。
  4. 遍历文件内容并使用std::strcmp/std::strncmp 查找字符串。
  5. 用完后释放内存。

使用有几个问题

const unsigned int bufferSize = 9;

char fileSize[bufferSize];
while (RFile.read(fileSize, bufferSize)) {
    if (strcmp(fileSize, "filesize:") == 0) {
        cout << "Exists" << endl;
    }
}

问题 1

fileSize 实际包含字符串"fileSize:" 时,strcmp 行将导致未定义的行为,因为变量只有 9 个字符的空间。它需要一个额外的元素来保存终止的空字符。你可以使用

const unsigned int bufferSize = 9;

char fileSize[bufferSize+1] = {0};
while (RFile.read(fileSize, bufferSize)) {
    if (strcmp(fileSize, "filesize:") == 0) {
        cout << "Exists" << endl;
    }
}

解决这个问题。

问题 2

您正在以 9 块为单位读取文件的内容。

第一次调用 RFile.read 读取第一个 9 个字符块。
第二次调用 RFile.read 读取第二个 9 个字符块。
第三次调用 RFile.read 读取第三个 9 个字符块。等等

因此,除非字符串"fileSize:" 位于此类块的边界,否则测试

if (strcmp(fileSize, "filesize:") == 0)

永远不会过去。

【讨论】:

  • “从文件读取所有内容到分配的内存” - 或者只是内存映射文件......?对我来说似乎更简单。
  • 我更新了我的代码 strcmp/strncmp 没有找到字符串。另一件事,该文件可能以千兆字节为单位太大,所以,我认为如果我将整个内容复制到内存中以查找字符串,那将是一个不好的方法。
  • @LionKing,除非字符串的位置能被 9 整除,否则这将不起作用。
  • “字符串的位置可以被9整除”,抱歉,能否详细解释一下这一点?
  • @LionKing“文本文件大小:其他文本”。您将阅读“文本文件”,然后阅读“大小:其他”。虽然我不确定你的代码是否安全,因为我不熟悉 RFile 并且不知道它是否为 null 终止缓冲区。看起来不像,因为“文件大小:”是 9 个字节。如果它没有被终止,那也会导致它永远找不到匹配项。
猜你喜欢
  • 2011-09-20
  • 1970-01-01
  • 2021-12-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-16
  • 2015-10-19
  • 2020-02-28
  • 2021-08-09
相关资源
最近更新 更多