fstream seekp / seekg



  • Salve,
    ich öffne eine Testdatei mit

    fstream datei("test.txt", ios::in | ios::out | ios::binary);
    

    und lass mir die Positionen tellg() und tellp() ausgeben, beide sind 0.
    Nun verändere ich via seekp(1) die Schreibposition, lass mir noch mal die beiden Positionen ausgeben, und beide Positionen sind jetzt 1.
    Das verwirrt mich etwas, ich hätte erwartet, dass die Leseposition davon unberührt bleibt.
    Aufgefallen ist mir das überhaupt erst, weil ich festgestellt habe, dass nach einer Leseoperation auch die Schreibposition verändert war.
    Nach ein paar oberflächlichen Experimenten habe ich den Eindruck, dass die beiden Positionen immer den gleichen Wert haben, dann frage ich mich natürlich, warum gibt es überhaupt zwei 'unterschiedliche' Attribute?



  • Ich glaube mal gelesen zu haben, dass oftmals nur 1 Pointer verwendet wird. D.h. put- und get-Pointer beziehen sich auf denselben Pointer.

    Das habe ich auch noch eben gefunden: http://stackoverflow.com/questions/6081700/tellg-moves-after-write-operation-in-file



  • Schau mal hier: 136. seekp, seekg setting wrong streams? Schaut man nun im Draft n3337 nach, so wurden die Proposals umgesetzt. In VS10 wurden die Proposals auch umgesetzt. Dennoch funktioniert es nicht wie gewünscht. 😃



  • Tja ... ich habe mittlerweile ein bisschen weiter herumexperimentiert. Was ich auch seltsam finde, ist:
    Ich lese ein paar Byte ab Dateiposition 0 in einen Buffer, ändere ein paar ab, setze via seekp die Position zurück und schreibe den Buffer zurück.
    Nun geben tellg und tellp die erwartete Position - 0 + gcount() zurück.
    Wenn ich aber nun einfach weiterlese, weil ich denke, die Leseposition stimmt ja eigentlich, dann funktioniert das offensichtlich nicht korrekt. Ich muss nun erst via seekg auf die gewünschte (die mir aber von tellg schon zurückgegeben wird) Position setzen.
    Ich meine, das was ich will, kriege ich letztendlich hin, aber ich muss ein paar Dinge veranstalten, die ich merkwürdig finde:

    #include <iostream>
    #include <fstream>
    
    using namespace std;
    
    void tellPositions(fstream &s)
    {
       cout << s.tellp() << ' ' << s.tellg() << '\n';
    }
    
    int main()
    {
       fstream datei("test.txt", ios::in | ios::out | ios::binary);   
    
       tellPositions(datei);
    
       streampos writePos = 0;
       streampos readPos = 0;
    
       do
       {
          char buffer[4];
          datei.seekg(readPos);
          datei.read(buffer, 4);
    
          cout << "*" << datei.eof() << "*" << datei.gcount() << "\n";
    
          for(size_t i = 0; i < datei.gcount(); ++i)
             if(buffer[i] == 'D')
                buffer[i] = 'X';
    
          datei.seekp(writePos);
          datei.write(buffer, datei.gcount());
          writePos = writePos + datei.gcount();
          readPos = readPos + datei.gcount();
    
          tellPositions(datei);
       }while(datei);
    
    }
    

    so funktioniert alles, wobei ich zunächst erwartet hatte, das die Positionierung in Zeile 24 unnötig ist, aber ohne die geht es nicht.



  • ISO/IEC 14882:2011 schrieb:

    The restrictions on reading and writing a sequence controlled by an object of class basic_filebuf<charT,traits> are the same as for reading and writing with the Standard C library FILE s.
    In particular:
    — If the file is not open for reading the input sequence cannot be read.
    — If the file is not open for writing the output sequence cannot be written.
    A joint file position is maintained for both the input sequence and the output sequence.

    Mal ganz unabhängig von all dem obigen: Wieso musst du eigentlich gleichzeitig in der selben Datei lesen und schreiben!?



  • Ich habe hier eine Datei, die via ftp von einem IBM-Mainframe kommt, und in der aus unerfindlichen Gründen aus 0xFF 0x9F gemacht wird. Für eine schnelle Problemlösung will ich die Datei nun einfach blockweise einlesen, aus 0x9F wieder 0xFF machen und zurückschreiben.
    So spare ich kopieren/löschen/umbenennen.


  • Mod

    Belli schrieb:

    Ich habe hier eine Datei, die via ftp von einem IBM-Mainframe kommt, und in der aus unerfindlichen Gründen aus 0xFF 0x9F gemacht wird. Für eine schnelle Problemlösung will ich die Datei nun einfach blockweise einlesen, aus 0x9F wieder 0xFF machen und zurückschreiben.
    So spare ich kopieren/löschen/umbenennen.

    Und da entwickelst du jetzt stundenlang eine eigene Lösung, anstatt da schnell ein sed drüberlaufen zu lassen?



  • Ich weiß nicht, was ein sed ist, und stundenlang ist nicht ansatzweise richtig.



  • Gut, in dem Fall macht es evtl. Sinn, das zu tun. Aber könntest du die Umwandlung nicht eigentlich schon beim Empfangen über FTP erledigen, bevor die Daten überhaupt in der Datei landet?

    sed: http://en.wikipedia.org/wiki/Sed



  • Mhm, hab das Lesen bei 'Unix Utility' abgebrochen. Ich habe hier einen Windows-Rechner.
    Im übrigen versuche ich hier nicht ausschließlich, meinen Job zu erledigen, sondern auch immer noch etwas hinzuzulernen.
    Wer kann schon wissen, ob Lesen/Beschreiben einer Datei nicht nächste Woche schon wieder in einem anderen Zusammenhang interessant sein wird.



  • dot schrieb:

    Aber könntest du die Umwandlung nicht eigentlich schon beim Empfangen über FTP erledigen, bevor die Daten überhaupt in der Datei landet?

    Ich weiß nicht, ich bin nicht derjenige, der die Datei beschafft. Ich weiß nicht, ob sie mittels get vom Host geholt wird, oder via put vom Host gesendet ...
    Aber wenn ich sie zB via ftp get holen würde, dann muss ich doch direkt eine Zieldatei angeben?
    Mir wäre nicht bekannt, dass ich sie praktisch in einem Zug noch durch ein anderes Programm schicken (wahrscheinlich via | (Pipe) - Funktion?) kann ...


Anmelden zum Antworten