Wie kann ich Daten in einer Datei teilweise ändern



  • Hallo Forum,

    ich brauche eine Datei mit mehreren logischen Sätzen aus integer- und string-Werten. Dann möchte ich einzelne Werte der Sätze in der Datei ändern. Zu Testzwecken habe ich es mit string-Daten probiert wie in den nachstehenden Funktionen.

    Wenn ich nun einen Wert überschreiben will, (z.B: ab Byte 12 in der Länge 6) steht dann in der Datei bis zum Byte 12 lauter Nullen, dann der zu ersetzende Text und der Rest der Daten ist weg. Was muss ich tun damit das funktioniert?

    int writeBinaryFile(string path, string& s, int firstByte) {
      int lastByte = -1;                              //nächstes Byte od Fehler: -1
      ofstream f(path, ios::binary);
      if (f) {
        f.seekp(firstByte);
        f.write((char*)s.c_str(), s.length());
        if (f) {
          lastByte = f.tellp();
          f.close();
          return lastByte;
        }
      }
      System::Windows::Forms::MessageBox::Show("(writeBinaryFile) Schreib-Fehler!");
      f.close();
      return lastByte;
    } /// end func writeBinaryFile
    
    int readBinryFile(string path, string& s, int firstByte) {
      int lastByte = -1;
      ifstream f(path, ios::binary);
      if (f) {
        f.seekg(firstByte);
        f.read(&s[0], 78);
      }
      return lastByte;
    }
    

  • Mod

    Dein Modus zum Öffnen der Datei muss ios::in | ios::out | ios::binary sein. Wobei ein ofstream schon out impliziert, das kannst du also auch weglassen. Das in mag komisch aussehen, aber macht eben das, was du willst, nämlich das weder die Datei ersetzt (das hast du jetzt), noch angehängt wird. Diese ganzen Kombinationen der Dateimodi sind ein bisschen komisch und unintuitiv. Kommt aus der Frühzeit der Computerprogrammierung. Muss man einfach wissen, logisch herleiten ist schwierig.

    Sei dir aber bewusst, dass das die Daten an der angesprungenen Stelle überschreibt, nicht einfügt. Einfügen geht nicht.



  • @SeppJ Danke Sepp, auf diese Idee wäre ich nie gekommen, jetzt funktioniert das!



  • Alternativ müßte auch fstream f(path, ios::binary) funktionieren, da dieser schon implizit ios::in | ios:out benutzt.

    Trotzdem ist es eigenartig, daß die Daten gelöscht werden, da es noch ios::trunc dafür gibt: ios_base::openmode.
    Aber laut Tabelle in std::basic_filebuf<CharT,Traits>::open gibt es nur einen Unterschied, wenn man ios::in | ios:out benutzt - bei nur ios::out oder ios:out | ios::binary wird implizit immer ios::trunc verwendet).

    PS: Ich habe jetzt auch immer, der Kürze wegen, ios geschrieben, auch wenn openmode eigentlich in der Basisklasse ios_basedefiniert ist, obwohl es nur als typedef definiert ist, s. basic_ios (bzw. ich erinnere mich, daß es in früheren Versionen noch eine von ios_base abgeleitete Klasse war).



  • @Th69 Ja, das mit fstream habe ich mir auch schon gedacht.



  • @znieh99

    um mit Niklaus Wirth (* 15. Februar 1934 in Winterthur; † 1. Januar 2024 in Zürich) zu antworten: Wahlfreier Zugriff (Random Access) findet nicht auf Dateiebene sondern im Hauptspeicher statt. Denn: Dateien sind Sequenzen, sie werden sequentiell gelesen und sequentiell geschrieben.

    Das heißt: Lese den Dateiinhalt auf eine zweckmäßige Datenstruktur (Array, Liste, Map o.ä) und bearbeite diese. Anschließend schreibe diese Daten zurück in die Sequenz (Serialize). Die Frage ist also, wie man abstrakte Datentypen in Sequenzen serialisiert und umgekehrt. Und aus OOP-Sicht könnte man die Daten im RAM als Objekte auffassen die dafür ihre eigenen Methoden bescheiben.

    MFG


Log in to reply