在输入流中搜索字符串
Searching for a string in an input stream
我有一个大的二进制文件(许多千兆字节,因此无法将其加载到内存中),我想搜索字符串"icpf"的所有出现。
我尝试为此使用 std::search
,但只是因为 std::search
仅适用于前向迭代器,而不适用于输入迭代器这一事实而感到困惑。
标准库是否为此提供了快速替代方案?还是我需要手动编码搜索(一次读取块然后std::search
这些块,或者ignore
所有内容直到"i",然后手动检查接下来的三个字符)?
标准库是否为此提供了快速替代方案?
尽管标准C++库提供了搜索文本流的方法,但它没有为二进制流提供类似的算法。
还是我需要手动编码搜索(一次读取块然后
std::search
这些块,或者忽略所有内容直到'i'
,然后手动检查接下来的三个字符)?
编写"跳过和搜索"方法可能很棘手,因为编写跳过条目的解决方案很容易。例如,如果要在包含"icpicpf"
的文件中查找"icpf"
,则一次处理一个字符的简单程序在丢弃"icpi"
前缀后将无法找到"icpf"
如果你打算自己编写代码,请考虑实现Knuth-Morris-Pratt算法。网上有许多实现,它在流上可以正常运行,因为它一次考虑一个字符,并且永远不会返回。
最快的方法是将整个文件加载到内存中,然后搜索内存。
下一个最佳选择是保持硬盘驱动器运动。 也许有一个线程将数据块读取到缓冲区中,另一个线程搜索缓冲区。
沿着列表向下,将大块数据读入缓冲区,然后搜索缓冲区是一种很好的技术,尽管不如以前的方法有效。
您可以使用std::getline
和std::string
逐行阅读。 这不如块读取快,因为输入函数正在搜索换行符(并在std::string
中分配内存)。
最糟糕的情况可能是逐个字符阅读。 函数开销对于读取单个字符不利(通常读取大块数据的开销相同)。
不,没有用于搜索文件的标准C++库功能。 某些操作系统具有用于搜索文件的实用程序;也许您可以使用其中之一。
编辑 1:
瓶颈是输入数据。 一旦你把数据放到缓冲区里,那么就会有许多有效的搜索算法,而不是蛮力(搜索第一个字母,然后搜索下一个字母,等等)。
在互联网上搜索"字符串搜索算法"。
有任何纯标准库解决方案,但内核已经实现了预取,所以应该可以mmap()
文件以获得所需的转发迭代器:(错误处理省略)
size_t search(int fd, size_t fileSize) {
auto start = reinterpret_cast<char*>(
::mmap(nullptr, fileSize, PROT_READ, MAP_PRIVATE | MAP_NORESERVE, fd, 0));
::madvise(start, fileSize, MADV_SEQUENTIAL);
auto pattern = "icpf";
auto offset = std::search(start, start+fileSize, pattern, pattern+4);
return offset - start;
}
这是一个小小的信念飞跃,相信你的内核可以正确地进行延迟加载、预取和丢弃。另一方面,如果你可以信任任何人,那可能是内核开发人员。
免责声明:我实际上并没有在数 GB 的文件中对此进行测试。
- 哪个更快:在 1d 向量中按字符串搜索还是在 2d 向量中按向量搜索?
- 有序地图字符串搜索与整数搜索之间的时间复杂度
- 使用图形的字符串搜索算法?C++
- C++子字符串搜索 - 跳入C++
- 字符串搜索 - 并行版本较慢
- 使用Robert Sedwick书中的符号表进行字符串搜索
- C++中的部分字符串搜索
- 哪个是更好的字符串搜索算法?Boyer-Moore或Boyer Moore Horspool
- 如何使用 c++ 将字符串搜索到字符串数组中
- 使用 C++ 在文件中进行字符串搜索/索引
- Qt5 中字符串搜索的最佳容器
- 优化.txt文件中的字符串搜索
- 字符串搜索输入中包含的单词
- Boyer-Moore-坏字符规则实现子字符串搜索
- 带星号*通配符的字符串搜索
- c++字符串搜索函数
- 最好的字符串搜索算法
- 通配符字符串搜索算法
- 在c++中使用字符串(搜索字符串,分割字符串,cout<<字符串)
- Strstr()函数重叠字符串搜索