Datei durchsuchen
-
Hallo
Ich habe folgendes Problem.
Ich möchte eine Logdatei durchsuchen nach einem bestimmten string von oben nach unten.
Dies stellt kein Problem dar, nun ist es aber so, dass ich ab diesem gefundenen string nach oben weitersuchen muss.
Wie kann getline dazu bewegen um zurück zu springen?Anbei der bereits vorhandene Code:
#include <iostream> #include <string> #include <fstream> int main() { std::ifstream infile("input.txt"); std::string strUPOC = "1"; int found; //std::ofstream outfile("output.txt"); if( infile.is_open() /*&& outfile.is_open()*/ ) { std::string strLine; while( std::getline(infile, strLine) ) { found=strLine.find(strUPOC); if (found!=std::string::npos) { std::cout << strLine << std::endl; } } infile.close(); //outfile.close(); } system("PAUSE > NUL"); return 0; }[e]upsilon[/e]
-
http://www.cplusplus.com/reference/iostream/istream/seekg/
Oder merk dir den Inhalt der Datei, den du vorher gelesen hast.
-
Besten Dank für die schnelle Antwort.
Das mit dem Inhalt merken ist ein guter Ansatz, die Datei an sich schwankt zwischen 200 und 300 MB aber von dem gefundenen String brauche ich nur ca. 20 Zeilen davor.
Aber geht das ganze so nicht in die Knie, bei einem so grossen File, wenn ich mir jeweils 20 Zeilen merken würde?Gruss
-
Nö, du cache'st (sorry für die Ausdrucksweise^^) jedes getline() in einer Liste und schmeißt bei jedem Durchgang die älteste Zeile raus, sobald du eben mehr als 20 hast.
-
Ja das klappt ja wunderbar
um ne 200 MB Datei zu durchsuchen dauert es ca. genau 30 sec.
wenn ich die letzten 20 Zeilen zwischenspeichere geht das ganze nur eine sec länger.So habe ich dies gelöst, gibt es eine bessere Variante?
std::string strLineBefore[20]; int CountLines = 0; if (CountLines > 19) { CountLines = 0; strLineBefore[CountLines] = strLine; } else { strLineBefore[CountLines] = strLine; CountLines++; }Gruess
-
Pardalis schrieb:
Ja das klappt ja wunderbar
um ne 200 MB Datei zu durchsuchen dauert es ca. genau 30 sec.
wenn ich die letzten 20 Zeilen zwischenspeichere geht das ganze nur eine sec länger.So habe ich dies gelöst, gibt es eine bessere Variante?
std::string strLineBefore[20]; int CountLines = 0; if (CountLines > 19) { CountLines = 0; strLineBefore[CountLines] = strLine; } else { strLineBefore[CountLines] = strLine; CountLines++; }Gruess
Wüsste jetzt keine bessere Lösung. Natürlich kann man auch einen Vector nehmen und vorne pushen und hinten poppen, aber der kann Geschwindigkeitstechnisch natürlich nicht mit einem rohem Array nicht mithalten.
-
Mit Vector kenne ich mich sowieso nicht aus

Ich Poste dann mal den kompletten code wenn ich fertig bin, vielleicht kanns ja jemand gebrauchen.
kann man die Vektoren ähnlich wie ein Schieberegister (Digitalrechnik) brauchen?
Gruss
-
Du kannst dir auch mit tellg nur die Positionen merken und dann zurückspringen. Das müsste nochmal deutlich schneller gehen als das viele Stringkopieren. Aber wie du sagst, macht es ja geschwindigkeitsmäßig ohnehin wenig aus. Dann lohnt es sich nicht unbedingt, etwas Funktionierendes nochmal umzuschreiben.
P.S.: 30 s für 200 MB? Kommst mir irgendwie viel vor. Machst du da sehr aufwändige Sachen beim Einlesen oder hast du so einen langsamen Datenträger?
edit:
kann man die Vektoren ähnlich wie ein Schieberegister (Digitalrechnik) brauchen?
Vektoren sind denkbar ungeeignet für Schieberegister. Im Standard kommen da am ehesten die Datenstrukturen deque und list dran, besser ist aber eine eigene Klasse dafür. Das nennt man dann Ringpuffer. Gibt's natürlich auch schon fertig, beispielsweise in der 'boost' bibliothekssammlung.
-
Was ich genau mache..
Ich habe eine Datei, hier ein Auschnitt:
04.01.2010 06:45:54:187 2 RS232Communicator 0x69C CxFrame MainThread Info: Steuer Modul: strBarcode = 0100140226581691,lFPSyncID=9,lDruckenEin = 1,lUseStempelversatz=0,lPrintStempelVersatz = 0,lPrintPorto = 1,lPrintDate = 0,strKlische = ,strSI1=04,strSI2=05,strSI3=2,lLeistungNr=0 () 578C1AA9-89EC-413E-B9EF-DBC225B90384 04.01.2010 06:45:54:187 2 RS232Communicator 0x7BC --- <<Data Received: Frankier Modul: Frankier Modul, Lenght 8: NO END 578C1AA9-89EC-413E-B9EF-DBC225B90384 04.01.2010 06:45:54:203 2 RS232Communicator 0x7BC --- <<Data Received: Frankier Modul: Frankier Modul, Lenght 14:0x04 0x02 0x01 0x04 0x00 0x00 0x06 0x00 0x37 0x3b 0x30 0x3b 0x07 0x03 ) 578C1AA9-89EC-413E-B9EF-DBC225B90384in dieser Datei sind ungefähr 1.2 Mio Zeilen.
Ich suche in der Datei eigentlich nur nach dem string "strBarcode ="
Dies geschieht folgendermassen:
#include <string> #include <fstream> #include <time.h> ..... ... std::ifstream infile("input.txt"); if( infile.is_open()/*&& outfile.is_open()*/ ) { std::string strLine; std::cout << "searching..." << std::endl << std::endl; time (&start); while( std::getline(infile, strLine) ) { if (strLine.find(strSearchStringUPOC)!=std::string::npos) {Dies dauerte 30s.
Ich war mit den 30s eigentlich recht zufrieden ach ja und die Harddisk ist eigentlich recht flott. Gibt es denn noch was schnelleres als getline/find?
Edit: Das mit den 30 s war Debug Code, mit dem Release Code geht nur noch 9 s

Gruss