kostenloser Webspace werbefrei: lima-city


Daten Byte-weise mit C oder C++ in andere Datei kopieren

lima-cityForumProgrammiersprachenC/C++ und D

  1. Autor dieses Themas

    chst

    chst hat kostenlosen Webspace.

    Hallo,

    nach einem kurzen Einblick in C/C++ im Informatikunterricht und die abschreckende Wirkung habe ich nun einen neuen Anlauf gestartet - und bin leider recht bald wieder gescheitert, weil die neue Datei um insgesamt 8 Zeilen (bei 12500 eingelesenen) zu lang wird:

    Mein Ziel war es, dass ich aus einer Datei den Header einlesen und auswerten wollte, und dann die nachfolgenden Daten in eine weitere Datei kopieren wollte. Ich habe meine Versuche zur einfacheren Nachvollziehbarkeit kommentiert..

    Den Header auszulesen hat schon mal funktioniert:
    streampos size;
      streampos size_header;
      char * memblock;
    
      ifstream file ("abc.txt", ios::binary);
      if (file.is_open())
      {
        file.seekg (0,ios::end); //setzt Cursor ans Ende der Datei
        size = file.tellg(); //ermittelt die Dateigröße
        memblock = new char [size]; //erstellt ein Array auf Basis der Dateigröße
        file.seekg (0, ios::beg); //setzt den Cursor an den Anfang der Datei
        file.read (memblock, size); //liest die Datei vollständig ins Array ein


    Die Berechnung meiner gesuchten Werte funktioniert - das habe ich mittels "cout" überprüft.

    delete[] memblock; //löscht die eingelesenen Daten zur Sicherheit wieder
        size_header = size - (streampos)(Datenmenge); //"Datenmenge" habe ich aus dem Header - die Differenz ergibt die variable Headerlänge von etwa 100 Bytes
        memblock = new char [size - size_header]; //erstellt erneut das Array - diesmal um den Header gekürzt
        
        file.seekg (size_header, ios::beg); //hüpft in der Datei nach den ermittelten Header
        file.read (memblock, (streampos)(Datenmenge)); //liest alle Daten nach dem Header ein
    
        ofstream file_neu; //erstellt die Variable zum Schreiben in neue Datei
        file_neu.open("test1.txt",ios::out); //erstellt und öffnet die neue Datei
        file_neu.write(memblock, (long)(Datenmengel)); //schreibt die zuvor eingelesenen Daten in die neue Datei
        file_neu.close(); //schließt die neue Datei
    
      }
    file.close(); //schließt die alte Datei


    Habt ihr vielleicht eine Idee, ob ich auf dem richtigen Weg bin, oder wo mein Problem liegen könnte?

    Besten Dank für eure Unterstützung!

    #################################################################

    News: Ich habe inzwischen noch eine zweite Variante getestet, die auf ein zweites Einlesen der Datei verzichtet und direkt das Array in die neue Datei schreibt:

    ofstream file_neu;
        file_neu.open("test1.raw",ios::out);
        for (long i = size_header; i <= size; i++)
        {
        file_neu << memblock[i];
        }
        file_neu.close();


    Leider hat auch das keinerlei Veränderung gebracht :(

    Beitrag zuletzt geändert: 2.6.2017 12:15:17 von chst
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. Wenn du die Datei schon komplett im Speicher hast, musst du sie tatsächlich nicht nochmal einlesen. Die Schleife mit der byteweisen Ausgabe in die Datei ist aber auch nicht wirklich brauchbar.

    Du kannst bei einem char-Pointer einfach einen Wert dazuaddieren, dadurch verschiebt sich der Pointer.
    char *nutzdaten = memblock + size_header;
    nutzdaten
    steht jetzt direkt nach den Headern und du kannst mit Hilfe von write() die Daten ab hier in eine Datei schreiben.

    Ansonsten: Was genau ist dein Problem? Ist es das hier:
    chst schrieb:
    [...] und bin leider recht bald wieder gescheitert, weil die neue Datei um insgesamt 8 Zeilen (bei 12500 eingelesenen) zu lang wird:
    Dann müsstest du mir erklären, was "8 Zeilen zu lang" bedeutet. Die Zeilen können ja nicht aus dem Nichts kommen, also was genau ist am Ergebnis falsch?
  4. Autor dieses Themas

    chst

    chst hat kostenlosen Webspace.

    Hallo,

    zunächst vielen Dank für den Tipp mit dem Pointer - die Umstellung hat mit deiner Anleitung sofort funktioniert!
    Leider hat sich aber am Ergebnis keinerlei Änderung ergeben - ich habe unter https://www.dropbox.com/sh/581twy2fw5tlg9q/AAAnn3FolT9-wqjXQHw0m_lFa?dl=0 mit a.txt die eingelesene, mit b.txt die Ausgabe hochgeladen.
    Außerdem habe ich als minimalbeispiel.cpp meinen Code bereitgestellt - diesmal zur besseren Übersicht mit konstantem Header von 100 Bytes.

    Zunächst ist mir aufgefallen, dass die Ausgabedatei größer ist anstatt kleiner - ich hätte erwartet, dass die Datei von 2.097.252 Bytes auf 2.097.152 Bytes verkleinert wird.
    - Mit Notepad++ habe ich beide Files geöffnet und die Differenz in den Zeilen erkannt.
    - Anschließend habe ich mit dem TotalCommander die beiden Files verglichen und kaum Übereinstimmungen gefunden.

    Und nun stehe ich vor einem großen Rätsel - eigentlich hatte ich dieses Projekt mit Ein- und Ausgabe als guten Einstieg gesehen... (Die große Datei ist leider sehr unübersichtlich - mit einer kleinen extra zum Testen erstellten Datei mit 150 Bytes funktioniert alles perfekt).

    Vielen Dank für jede Unterstützung!
  5. Ich habe mir die 3 Dateien einmal heruntergeladen. Wenn ich minimalbeispiel.cpp kompiliere und ausführe (Linux), bekomme ich eine neue Datei, in der genau die vorderen 100 Byte fehlen - wie erwartet.

    Dass Windows hier andere Ergebnisse liefert, liegt vermutlich an Zeile 36:
    file_neu.open("b_my.txt",ios::out);
    Füge hier einmal noch das binary-Flag hinzu:
    file_neu.open("b_my.txt",ios::out | ios::binary);

    Ich konnte jetzt nicht selbst testen ob das die Ursache war, weil ich gerade kein Windows zur Hand habe.


    Edit:
    Noch ein Hinweis, ich schrieb vorher von der Schleife, die man eher vermeiden sollte. Damit meite ich z.B. sowas, Zeile 38-41:
    for (long i = 0; i <= (size-size_header-1); i++)
    {
        file_neu << nutzdaten[i];
    }
    Du kannst die Daten einfach mit write() schreiben und benötigst keine Schleife. Das ist um Größenordnungen schneller. (auch wenn das bei 2MB vielleicht noch nicht so bemerkbar ist.)
    Konkret heißt das, du kannst diese Schleife komplett durch folgenden Befehl ersetzen:
    file_neu.write(nutzdaten, size-size_header);


    Beitrag zuletzt geändert: 2.6.2017 21:47:40 von fuerderer
  6. Autor dieses Themas

    chst

    chst hat kostenlosen Webspace.

    Grüß' dich,

    herzlichen Dank für deine Unterstützung und die super nachvollziehbaren Codes und Tipps - mit ios:binary gab es plötzlich das richtige Output-File, und der Schleifen-Ersatz hilft (abgesehen von der Geschwindigkeit) hilft der Übersichtlichkeit!

    Dir einen schönen Abend!
  7. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!