Datei öffnen und Zeilen verschieben
-
Morgen zusammen,
Ich möchte gerne ein File einlesen und falls "MWR154=" vorkommt, soll
es in die zweite Zeile der selben Datei verschoben werden. Falls das gesuchte an einer anderen Stelle nochmals vorkommt, soll er diese dann nach Zeile 3 verschieben.Bsp.
Das
ist
ein
Beispiel
MWR154=30
Weiter
MWR154=34Output
Das
MWR154=30
MWR154=34
ist
ein
Beispiel
WeiterSoweit bin ich bis Dato:
int main(int argc, char *argv[]) { ifstream f; // Datei-Handle f.open(argv[1], ios::in); // Öffne Datei aus Parameter int i=0; while (!f.eof()) // Solange noch Daten vorliegen { getline(f, s); // Lese eine Zeile Zeile[i]=s; i++; } for (k=0; k<i; k++) { string::size_type loc1 = Zeile[k].find( "MWR154=", 0 ); if( loc1 != string::npos ) { !!!! HELP !!!! } else { } } f.close(); // Datei wieder schließen return 1; }
Wie kann ich die Zeile nun auschneiden und wieder einfügen? Stelle Quellcode --> !!!!HELP!!!!..
Geht dies überhaupt mit ifstream ? Blicke hier nicht so ganz durch und würde mich über Vorschläge/Verbesserungstipps freuen...
-
Einfach zu verschieben ist wahrscheinlich nicht so einfach. Der Ablauf sollte sein:
(a) Zeilenweise einlesen (abspeichern bspw. in list<string>)
(b) Alle Einträge mit "MWR154=" am Start suchen und in der Liste verschieben (Wahrscheinlich mit einer Kombination aus list.remove und list.insert)
(c) Zeilenweise die Datei neu schreibenMfG SideWinder
-
SideWinder schrieb:
Einfach zu verschieben ist wahrscheinlich nicht so einfach. Der Ablauf sollte sein:
(a) Zeilenweise einlesen (abspeichern bspw. in list<string>)
(b) Alle Einträge mit "MWR154=" am Start suchen und in der Liste verschieben (Wahrscheinlich mit einer Kombination aus list.remove und list.insert)
(c) Zeilenweise die Datei neu schreibenMfG SideWinder
Ich würde eine zweite Datei aufmachen, und von der ersten entsprechend kopieren. Wenn alles gut gelaufen ist, dann löscht Du die original Datei und bennenst die neue entsprechend um. Wenn was schief geht, bleibt die original Datei erhalten.
-
Ich stimme Tachyon zu - in einer Datei in-place herumzufuhrwerken, ist immer gefährlich (was passiert bei Stromausfall?).
Was den Algorithmus angeht: Ich denke, es wäre einfacher, die verschiedenen Zeilentypen gleich beim Einlesen in verschiedene Container zu sortieren. Ich stelle mir das etwa so vor:
#include <algorithm> #include <cstdio> #include <deque> #include <fstream> #include <iostream> #include <iterator> #include <stdexcept> #include <string> #ifdef _WIN32 # define NOMINMAX # include <windows.h> #else # include <unistd.h> #endif void enforce(bool condition, std::string const &message) { if(!condition) throw std::runtime_error(message); } int main() { std::string first_line; std::deque<std::string> lines_mwr; std::deque<std::string> lines_other; char const *const filename_in = "datei.txt"; { std::ifstream in(filename_in); std::string line; enforce(std::getline(in, first_line), "Fehler beim Lesen der Eingabedatei"); while(std::getline(in, line)) { if(line.compare(0, 7, "MWR154=") == 0) { lines_mwr .push_back(line); } else { lines_other.push_back(line); } } } char filename_tmp[L_tmpnam]; { // In Produktionscode evtl. besser auf tmpfile() zurückgreifen. Das ist zwar C, // schließt aber eine Race-Condition aus. enforce(std::tmpnam(filename_tmp) != 0, "Temporärer Dateiname konnte nicht generiert werden"); std::ofstream out(filename_tmp); enforce(out, "Temporäre Datei konnte nicht erstellt werden"); out << first_line << '\n'; std::copy(lines_mwr .begin(), lines_mwr .end(), std::ostream_iterator<std::string>(out, "\n")); std::copy(lines_other.begin(), lines_other.end(), std::ostream_iterator<std::string>(out, "\n")); } #ifdef _WIN32 MoveFileEx(filename_tmp, filename_in, MOVEFILE_REPLACE_EXISTING | MOVEFILE_WRITE_THROUGH); #else rename (filename_tmp, filename_in); #endif }
-
Luftikus schrieb:
Ich möchte gerne ein File einlesen und falls "MWR154=" vorkommt, soll
es in die zweite Zeile der selben Datei verschoben werden. Falls das gesuchte an einer anderen Stelle nochmals vorkommt, soll er diese dann nach Zeile 3 verschieben.Alles einlesen sortieren und wieder ausgeben - ist aber jeden Fall die richtige Vorgehesweise. Und beim Sortieren erledigt std::stable_sort schon alles für Dich.
#include <algorithm> // stable_sort, copy #include <fstream> #include <iostream> #include <iterator> // ostream_iterator #include <string> #include <vector> struct compareStr { explicit compareStr( const std::string& prefix ) : m_prefix( prefix ) {} bool operator()( const std::string& a, const std::string& b ) const { // 'a' ist genau dann "kleiner" als 'b', falls a das prefix enthält und b nicht. return a.substr( 0, m_prefix.size() ) == m_prefix && b.substr( 0, m_prefix.size() ) != m_prefix; } private: std::string m_prefix; }; int main( int argc, char* argv[] ) { using namespace std; if( argc < 2 ) { cerr << "Bitte Dateinamen angeben" << endl; return -1; } vector< string > lines; { // vector 'lines' aus Datei füllen ifstream datei(argv[1]); if( !datei.is_open() ) { cerr << "Datei '" << argv[1] << "' nicht gefunden" << endl; return -1; } for( string line; getline( datei, line ); ) lines.push_back( line ); } if( lines.size() > 1 ) // Bem.: erst ab der zweiten Zeile sortieren stable_sort( ++lines.begin(), lines.end(), compareStr("MWR154=") ); { // sortierte Zeilen wieder wegschreiben ofstream datei(argv[1]); copy( lines.begin(), lines.end(), ostream_iterator< string >( datei, "\n" ) ); } return 0; }
Gruß
Werner
-
Danke für die guten Vorschläge...Habe mich heute früh mal Werner seiner
guten Lösung gewidmet. Funktioniert super...Nur zum Verständnis, was ist wenn er die Zeilen an Stelle 3 der Datei schreiben soll ?Das ändern der If-Bedingung von 2 auf 3, bringt nicht den gewünschten Erfolg :
if( lines.size() > 2 )
-
if( lines.size() > 2 ) stable_sort( lines.begin() + 2, lines.end(), compareStr("MWR154=") );
Klappt so aber nur, wenn nicht vorher (vor Zeile 3) bereits ein MWR154= auftaucht, weil die ersten zwei Zeilen jetzt so bleiben, wie sie sind, siehe Werners Kommentar: "erst ab der zweiten Zeile sortieren", der nun natürlich heißen müsste: "erst ab der dritten Zeile sortieren".
-
Luftikus schrieb:
Habe mich heute früh mal Werner seiner guten Lösung gewidmet.
-
...