我想读取一些大文件内容并检查一些列,然后根据示例行的列值存储一些文件行:
7774777761 72288833 2015/03/20 23:59:37 26 26 38
99944524 09671017 2015/03/20 23:59:44 18 1 8
我是这样用 Python 做的:
import sys
if __name__=="__main__":
if (len(sys.argv)<4):
sys.stderr.write('Usage: trk finame fout column value \n ')
sys.exit(1)
finame=open(sys.argv[1],'r')
result=open(sys.argv[2],'w')
nos=open("nos.txt",'w')
col=int(sys.argv[3])
val=sys.argv[4]
for l in finame:
llist=l.split()
try:
if llist[col]==val:
result.write(l)
except:
nos.write(l)
result.close()
nos.close()
然后尝试使用正则表达式在 C++ 中执行此操作:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;
int main(int argc, char* argv[])
{
ifstream fstr;
ofstream ofstr;
string istr,result;
int col;
string val;
if(argc<5){
cout<<"you must enter right arguments"<<endl;
cout<<"colgrab inputfile outputfile desired_col desired_val"<<endl;
cout<<"for example :"<<endl;
cout<<"colgrab TrkTicket.txt INCOM_HWI.txt 6 1"<<endl;
}else{
fstr.open(argv[1]);
ofstr.open(argv[2]);
col=atoi(argv[3]);
val=argv[4];
if(!fstr)
{
cerr << "File could not be opened" << endl;
exit( 1 );
}
if(!ofstr)
{
cerr << "File could not be opened" << endl;
exit( 1 );
}
}
while(getline(fstr,istr)){
// cout<<istr<<endl;
try {
regex re(R"XXX( *(\d+) +(\d+) +(\d+/\d+/\d+) +(\d+:\d+:\d+) +(\d+) +(\d+) +(\d+).)XXX");
std::smatch match;
//cout<<istr<<endl;
if (regex_search(istr, match, re) && match.size() > 1) {
result = match.str(col);
if(val==result){
ofstr<<istr<<endl;
}
//cout<<result<<endl;
} else {
//result = std::string("No match found");
//cout<<result<<endl;
}
} catch (std::regex_error& e) {
// Syntax error in the regular expression
//cerr<<"Syntax error in the regular expression "<<endl;
}
}
return 0;
}
我这样做的目的是提高速度。但让我感到惊讶的是,对于一个 270 Mb 的文件,Python 版本在不到 10 秒的时间内完成了这项工作,但 C++ 版本无法在 10 分钟内完成这项工作。
如何修复 C++ 版本以在更短的时间内完成这项工作?
Python 版本 python 3.2
C++ 版本 GCC G++ 4.9.1
编辑 1
我尝试了所有建议的方法,并且使用 MikeMB 方法它们几乎是均匀的:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <regex>
using namespace std;
int main(int argc, char* argv[])
{
ifstream fstr;
ofstream ofstr;
string istr,result;
int col;
string val;
if(argc<5){
cout<<"you must enter right arguments"<<endl;
cout<<"colgrab inputfile outputfile desired_col desired_val"<<endl;
cout<<"for example :"<<endl;
cout<<"colgrab TrkTicket.txt INCOM_HWI.txt 6 1"<<endl;
}else{
fstr.open(argv[1]);
ofstr.open(argv[2]);
col=atoi(argv[3]);
val=argv[4];
if(!fstr)
{
cerr << "File could not be opened" << endl;
exit( 1 );
}
if(!ofstr)
{
cerr << "File could not be opened" << endl;
exit( 1 );
}
}
while(getline(fstr,istr)){
stringstream sstr(istr);
int i = 0;
while (sstr >> result) {
if (i == col-1 && result == val) {
ofstr << istr << "\n";
break;
}
i++;
}
return 0;
}
有没有办法进一步提高性能?
最佳答案
编辑 1 的答案:
添加
std::ios::sync_with_stdio(false);
作为main()
的第一行 不错的速度提升。您不需要读取一行然后将其转换为
stringstream
- 您可以直接从fstr
读取值以避免复制。要在毫秒内获取数据,您可以使用索引数据格式,例如将数据导入 SQLite database ,索引列并使用数据库查询来提取它。
关于python - 使用 c++ 检索一些文本列比 python 慢得多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29782203/