I want to read some big file contents and check some column then store some lines of file based on the column value the sample line:
7774777761 72288833 2015/03/20 23:59:37 26 26 38
99944524 09671017 2015/03/20 23:59:44 18 1 8
I did it in Python this way:
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()
and then tried to do it in C++ using regexp:
#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;
}
My purpose to doing this was speed. But the thing surprised me was that Python version did the job in less than 10 sec for a 270 Mb file, but C++ version could not finish the job on 10 min.
How can I fix c++ version to do the job in less time?
Python version python 3.2
C++ version GCC G++ 4.9.1
Edit 1
I tried all proposed ways and with MikeMB way they are almost even :
#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;
}
is there a way to improve performance more?
l.split()you let python do, but I suspect that the main culprit is I/O. Replace theendlinofstr<<istr<<endlwith'\n'to avoid flushing all the time, does that change things?regex re(...);part outside of the while loop. Also: did you compile with optimizations?operator>>fromifstream? Or by usinggetlineand splitting it usingstringstream? I strongly suspect that using regular expressions is the issue here.