我有一个文本文件(约10GB),格式如下:
data1<TAB>data2<TAB>data3<TAB>data4<NEWLINE>
我希望能够扫描并只处理
data2
,在C++中提取data2
的最佳(最快)方法是什么。编辑:添加了NEWLINE
我有一个文本文件(约10GB),格式如下:
data1<TAB>data2<TAB>data3<TAB>data4<NEWLINE>
data2
,在C++中提取data2
的最佳(最快)方法是什么。逐行读取文件。对于每一行,按制表符进行分割。这将产生一个包含字段的数组,使您能够使用第二个字段(data2)。
cut -f2 # from stdin
cut -f2 <my_file # from file
void parse(std::istream& in)
{
std::string word;
while( in ) {
std::cin >> word; // throwaway 1
std::cin >> word; // data2
process(word);
std::cin >> word >> word; // throwaway 3 and 4
}
}
// ...
parse(std::cin);
std::ifstream file("my_file");
parse(file);
逐行读取文件。从那里解析出制表符非常简单。您可以使用类似于strtok()
或类似例程的东西。
由于文件大小相当大,您可能需要考虑使用一种技术,允许您将I/O与处理重叠。在回复评论时,您提到正在使用Linux。如果您使用的是2.6或更高版本的内核,则可以考虑使用Linux异步I/O(AIO)。具体而言,您将使用来排队一些读取请求,然后使用等待一个(或多个)请求结束。随着请求完成,您将使用普通的char*扫描缓冲区以定位您感兴趣的数据。对于找到的每个数据,您可以在那时创建一个std::string(尽管避免复制可能会更有益),并对其进行处理。扫描完一个块后,您将重新排队以从文件中读取另一个块。您将继续执行此操作,直到处理完文件中的每个块。
这种方法的代码将比逐行读取文件更复杂,但速度可能会快得多。
while (getline(std::cin, my_string)) ...
很慢(我还没有进行调查 - 奇怪的是 my_string
应该只重新分配几次内存,这是最明显的性能风险)。无论如何,aio_read
读取二进制块,更类似于 my_stream.read()
…… 我既没有使用过也没有听说过任何有关性能方面的投诉。在这些块读取之后,程序员必须额外工作以跟踪行/第二个字段,在第二个字段本身可能不完整的情况下处理部分行读取等等。这不是火箭科学,但内存映射要容易得多。 - Tony Delroy好的,打开一个文件流(应该能够处理10G的文件),然后跳到第一个制表符之后,也就是'\t'
,读取你的数据,然后跳到下一个换行符并重复。
#include <fstream>
#include <string>
int main(){
std::fstream fin("your_file.txt");
while(fin){
std::string data2;
char sink = '\0';
// skip to first tab
fin.ignore(1024,'\t');
fin >> data2;
// do stuff with data2
// skip to next line
fin.ignore(1024,'\n');
}
}
getline
也必须处理所有这些字符。strtok
也是如此,所以我想不行。 - Xeosink
永远不会是'\t'
或'\n'
。 - wilhelmtell#include <stdio.h>
...
FILE* fp = fopen(path_to_file, "r");
char[256] data;
while(fscanf(fp, "%*s<tab>%s<tab>%*s<tab>%*s", data))
{
do what you want with your data
}
%s
外面加星号?使用 %*s
可以抑制赋值。缺点是 %s
会在第一个空格处停止,所以如果数据中有空格,这种方法就不直接适用了。你可以使用 %100*[^\t]
来抑制 data1,使用 %100[^\t]
来捕获 data2 等等,但长度容易出错。 - Jonathan Leffler
dataN
部分有多长?是固定的还是可变的? - Xeo