我在BMP文件中查找二进制子字符串时遇到问题

I'm having issues finding binary substring in my BMP file

提问人:simsam 提问时间:10/17/2023 最后编辑:user4581301simsam 更新时间:10/24/2023 访问量:78

问:

所以我有一个小问题。我正在做一项学校作业,我只是不知道如何获得解决方案。因此,赋值需要我以二进制形式读取文件,然后在该读取文件中找到某些位序列。然后,我将打印出找到的序列中第一个位的索引,用于该序列的所有实例。

因此,如果我要编写一个二进制序列并搜索该序列,我将获得如下索引: .现在一切都很好,当我编写代码来为1和0的字符串执行此操作时,但是当我开始实现文件读取和搜索时,我遇到了一个问题。该文件是一个.bmp,以二进制形式读取它应该给我一个像素值的字符串(不太确定如何检查该字符串是否真的是我认为的)。然后,当我去搜索二进制子字符串时,当有很多时,它找不到它的任何实例。我的程序会返回,并且不会循环遍历字符串。1001100100101110110010, 4std::string::npos

这是我目前拥有的代码:


#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <filesystem>
using namespace std;

void f(vector<size_t>& poz, string pattern, string filename) {

    std::ifstream file(filename, std::ios::binary);
    if (file)
    {

        file.seekg(0, std::ios::end);
        std::streampos length = file.tellg();
        file.seekg(0, std::ios::beg);

        std::vector<char> buffer(length);
        file.read(&buffer[0], length);

        std::stringstream localStream;
        localStream.rdbuf()->pubsetbuf(&buffer[0], length);

        string solution = localStream.str();

        //after i get the full string i should be able to find the instances of my pattern
        //this file contains only white pixels and red (000000000000000011111111) pixels

        cout << "Pattern: " << pattern <<endl;
        size_t index = solution.find(pattern);
        cout << "First found pixel: " << index << endl; // this value is the exact same as npos
        cout << "string::npos: " << string::npos;
        while (index != string::npos) {
            poz.push_back(index);
            index = solution.find(pattern, index + pattern.size());
        }
    }
    
}

int main() {
    vector<size_t> poz;
    string file = "test.bmp";
    string pattern = "000000000000000011111111"; //looking for red pixels only

    f(poz, pattern, file);

    for (auto i = poz.begin(); i != poz.end(); i++) {
        if (i == (poz.end() - 1))
            cout << *i << endl;
        else
            cout << *i << ", ";
        
    }

}

我不知道我是否搜索了错误的序列,或者我的文件实际上没有转换为二进制字符串,这就是为什么搜索没有发现任何东西的原因。任何帮助都是值得赞赏的。

C++ 子字符串 fstream bmp sstream

评论

3赞 user4581301 10/17/2023
std::ifstream file(filename);以文本模式而不是二进制模式打开文件。不需要的字符替换可能会在程序真正启动之前就将其杀死。我推荐std::ifstream file(filename, std::ios::binary);
0赞 user4581301 10/17/2023
旁注:将文件读入向量的更好方法
0赞 user4581301 10/17/2023
旁注:您可以使用上述内容直接阅读 并使用 .std::stringstringstream
2赞 user4581301 10/17/2023
旁注:您从文件中读取的二进制数据实际上将是一个字节数组,而不是包含 1 和 0 的字符。换句话说,1001 将0x09您从文件中读取的数据中,除非您遍历输入数组并将每个位转换为适当的字符,否则它不会是完成此作业的正确工具。 可能对此有所帮助,但我不确定将文件分解为字符是最好的途径。std::string::findstd::bitset
1赞 Thomas Matthews 10/17/2023
这个作业(或者至少你发布的内容)有很多歧义。例如,如果我以 8 位数量进行搜索,则一些正数是:、、。使用较高的位(字)数量(例如 16 位或 32 位)时,情况会变得更糟。另外,该模式可以跨越单词边界或字节边界吗?101101001010101010111011101

答:

1赞 simsam 10/17/2023 #1

根据 @user4581301 的观察,我在解决方案之前读取的文件是作为字节传递的,因此我无法找到我希望的匹配项。更改我读取文件的方式解决了我的问题。我没有以二进制模式读取文件并将其直接存储到字符串中,而是决定读取字符,然后将它们转换为位集数组。然后,我将位集数组连接成一个字符串,并使用该函数查找我的出现次数。这个过程很慢,是的,但从技术上讲,按照我的问题工作。我的代码已更改以反映这一点。.find()

void f(std::vector<size_t>& poz, std::string pattern, std::string filename) {
    std::ifstream file(filename, std::ios::in | std::ios::out | std::ios::binary);

    if (file) {

        std::string fileString((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); // reading chars instead of bytes

        auto size = fileString.size();
        file.close();

        // Save the characters into 8 bit bitsets
        std::bitset<8>* bitsetFile = new std::bitset<8>[size];
        std::string convertedFile;
        for (int i = 0; i < fileString.size(); i++) {
            bitsetFile[i] = std::bitset<8>((int)fileString[i]);
            convertedFile = convertedFile + bitsetFile[i].to_string();
        }
        
        // use string function .find() to search for red pixels
        size_t index = convertedFile.find(pattern);
        while (index != std::string::npos) {
            poz.push_back(index);
            index = convertedFile.find(pattern, index + pattern.size());
        }
    }
}