fwrite überschreibt nicht



  • Hallo alle zusammen,
    ich arbeite im Moment an einem Programm zum auslesen und bearbeiten von *.spr Datein.
    Innerhalb dieser Datei ist eine PAL Farbtabelle welche ich gerne mit einer anderen ersetzen würde. Obwohl ich weiß das ich die Farbtabellen richtig auslesen habe ich das Programm so umgeschrieben das es die aktuelle Farbtabelle ausliest und sie dann einfach wieder überschreibt, d.h. das sich eigentlich garnichts ändern sollte.
    Dazu benutze ich fwrite , bei meinen bisherigen Versuchen hängt das Programm die Daten aber nur an anstatt sie zu ersetzen.

    struct TSprPalette
    {
     Byte Red;
     Byte Green;
     Byte Blue;
     Byte Alpha;
    };
    
    //---------------------------------------------------------------------------
    
    void __fastcall TForm1::btInfoClick(TObject *Sender)
    {
     TSprPalette PAL[256];
    
     //Open File
     FILE *myfile = fopen("test.spr", "r+b");
    
     //Get Color Palette
     fseek(myfile, -1024, SEEK_END);
     fread(&PAL, 5, 256, myfile);
    
     //Write Color Palette
     fseek(myfile, -1024, SEEK_END);
     fwrite(&PAL, 5, 256, myfile);
    }
    

    Ich hab bereits die Forum Suche benutzt aber bei den dort gefundenen threads lag der Fehler meistens bei dem fopen Parameter welchen ich ja extra auf "r+b" gesetzt habe und eben nicht auf "a". Deswegen verstehe ich nicht warum die Daten trotzdem angehangen und nicht überschrieben werden.
    Ich hoffe mir kann jemand helfen,

    mfg akeTsu



  • Plumpe Frage: Ich kenn' das Dateiformat nun nicht, hast Du aber beachtet, dass 5 * 256 nicht 1024 ist?



  • Ja ich weiß das 5 * 256 nicht 1024 ist. Seltsamerweise liest er wenn ich 4 angebe aber nur Rot, Gelb, Blau aus und nicht Alpha. Deswegen benutze ich 5 weil er dann alle 4 ausliest und auch wieder speichert. Ich weiß auch nicht warum.
    Aber das ist nicht das eigentliche Problem. Ich habe schon überprüft ob er alles richtig ausliest, das ist der fall. Das Problem ist halt das er es beim Speichern anhängt und nicht überschreibt.
    Über das Dateiformat müsste man in diesem Fall nur wissen das die letzten 1024 Bytes die Farbtabelle ist d.h. das diese bei EOF - 1024 anfängt.



  • eventuell gehts ja wenn du vor dem Schreiben den Dateizeiger nicht aufs Ende (SEEK_END) sondern auf den Anfang (SEEK_SET) setzt



  • Ich setzte den Dateifeiger nichtmals auf das Ende sondern auf die Stelle 1024 Bytes VOR dem Ende, genau da fängt die Farbtabelle jedesmal an. Welche offset address das vom Anfang aus ist weiß ich nicht.



  • Zweite plumpe Frage: Die Datei wird bei jedem Starten genau 256 bytes größer oder? Du solltest den Fehler mit den 4*256 beheben.



  • nope, sie wird genau 1024 Bytes größer. Genau die Datenmenge die ich auch speichern will, nur halt überschrieben/ersetzt und nicht angehangen >_<



  • Ich habe das mal getestet. Bei mir werden korrekt die letzten 1024b (4 * 256) überschrieben. Filemon.exe:

    19:30:07	Project1.exe:2076	QUERY INFORMATION	C:\Programme\CBuilder6\Projects\test\1\test.spr	SUCCESS	Attributes: A	
    19:30:07	Project1.exe:2076	OPEN	C:\Programme\CBuilder6\Projects\test\1\test.spr	SUCCESS	Options: Open  Access: 0012019F	
    19:30:07	Project1.exe:2076	QUERY INFORMATION	C:\Programme\CBuilder6\Projects\test\1\test.spr	SUCCESS	Length: 144128	
    19:30:07	Project1.exe:2076	READ 	C:\Programme\CBuilder6\Projects\test\1\test.spr	SUCCESS	Offset: 143104 Length: 1024	
    19:30:07	Project1.exe:2076	QUERY INFORMATION	C:\Programme\CBuilder6\Projects\test\1\test.spr	SUCCESS	Length: 144128	
    19:30:07	Project1.exe:2076	WRITE	C:\Programme\CBuilder6\Projects\test\1\test.spr	SUCCESS	Offset: 143104 Length: 1024
    

    Machst Du da noch andere Operationen? Vllt Datei mal schließen.



  • Ich weiß jetzt wo der Fehler lag. Bei Dateioperationen die ich davor ausführe habe ich mich ein bischen mit den Bits verrechnet. Danke für die Hilfe ^^



  • Hallo,

    es ist zwar schon das Meiste gesagt, ich finde es jedoch trotzdem merkwürdig eine Position so: "gehe zum Ende und dann 1024 Stellen zurück" anzugeben statt so: "gehe zur StartPosition". Am Anfangspunkt einer Datei befindet sich der Positionszeiger nach dem Öffnen der Datei mit fopen eh' immer, von daher könntest du dir das erste fseek sparen... Und das zweite fseek würde ich so angeben:

    fseek(myfile, 0, SEEK_SET);
    

    einfach weil das besser nachvollziehbar ist, evtl. auch für dich später, nicht nur für Andere die deinen Code lesen. 😉

    MfG



  • Es ist absolut korrekt, vom Fileende her zu operieren. Meines Wissens der einzige standardisierte Weg, plttformübergreifend die Dateilänge zu ermitteln(mal von der Sparse files-Problematik abgesehen)



  • Danke für die Erklärung witte. Was heißt jetzt plattformübergreifend? Wenn ich fseek(AnyFile, 0, SEEK_SET); benutze, was kann da gegenüber fseek(AnyFile, -1024, SEEK_END); schieflaufen? Und vor Allem: auf welchen Plattformen?



  • Mein Ausgangspunkt war: Stell' Dir vor, Du musst die Länge von Dateien ermitteln. Code soll z.B. auf Linux und Win lauffähig sein und willst es deshalb so standardkonform wie möglich machen. Wie ermittelt man die Dateilänge mit den Standardfunktionen? Datei zum lesen öffnen, Deskriptor ans Ende der Datei positionieren und Offset zum Fileanfang ermitteln. Ich kenne keinen anderen Weg. Sollte Filesystem-Handling nicht im nächsten C++-Standard mit aufgenommen werden?



  • Hallo

    Ja im nächsten C++ Standard gibt es dann das was heute noch als boost::filesystem bekannt ist.

    Bis dahin gibt es keine platformunabhängige Möglichkeit, nur portable (selbgemacht oder externer Bibliothek)

    bis bald
    akari



  • Bisher sieht es aber nicht so aus, als ob filesystem da noch reinkommt (TR2).
    Aber man kann ja auch boost verwenden.



  • witte schrieb:

    Mein Ausgangspunkt war: Stell' Dir vor, Du musst die Länge von Dateien ermitteln. Code soll z.B. auf Linux und Win lauffähig sein und willst es deshalb so standardkonform wie möglich machen. Wie ermittelt man die Dateilänge mit den Standardfunktionen? Datei zum lesen öffnen, Deskriptor ans Ende der Datei positionieren und Offset zum Fileanfang ermitteln. Ich kenne keinen anderen Weg. Sollte Filesystem-Handling nicht im nächsten C++-Standard mit aufgenommen werden?

    Ich weiß zwar nicht, was das mit dem Eröffnungspost zu tun hat... Wo steht denn etwas von Dateilänge ermitteln, oder Windows UND Linux? Da davon nirgendwo etwas steht, bin ich eher immer dafür den Code so nachvollziehbar und kurz wie möglich zu gestalten als mich auf hypothetische Anforderungen einzurichten. 😉

    MfG



  • Ich habe auf Deine Post geantwortet und sagen wollen dass das durchaus machbar ist. Wenn Du aus Lesbarkeitsgründen nur vom Dateianfang aus arbeiten willst, dann mach es doch einfach.



  • *lol*

    Ich glaub' wir reden aneinander vorbei witte... Ich frag' nochmal anders: Wenn man mit einem Programm für Windows eine Datei (Dateilänge ist bekannt) von Anfang bis Ende ausgelesen hat, die ausgelesenen Daten modifiziert hat und dann mit diesen Daten (Datenlänge unverändert) die Datei überschreiben möchte, ist es dann nicht übersichtlicher den Dateizeiger mit fseek(MyFile, 0, SEEK_SET) anstatt mit fseek(MyFile, -1024, SEEK_END) an den den Dateianfang zu setzen? Und die (für mich wichtigere) Hauptfrage: Was habe ich für einen Vorteil in diesem Szenario, wenn ich den Zeiger mit fseek(MyFile, -1024, SEEK_END) positioniere? Ich sehe nämlich im Moment nur den Nachteil, dass es in meinen Augen unlogisch ist einen Zeiger 1024 vor dem Ende zu positionieren, wenn man in auch einfach am Anfang positionieren kann... 😞

    MfG



  • akeTsu schrieb:

    Ich setzte den Dateifeiger nichtmals auf das Ende sondern auf die Stelle 1024 Bytes VOR dem Ende, genau da fängt die Farbtabelle jedesmal an. Welche offset address das vom Anfang aus ist weiß ich nicht.



  • OMFG - wer lesen kann ist klar im Vorteil... 🙄


Anmelden zum Antworten