Struct in Binärdatei schreiben - Länge variiert!



  • Werte Forumsbesucher,

    ich sitze über einer Sache, die mich fast zum Ausflippen bringt 😡 : Ich versuche, eine Textdatei auszuparsen und die Ergebnisse binär abzulegen. Dabei wird immer folgender Teil durchlaufen:

    typedef struct _abs32_ 
    {
    	long int abs_x;
    	long int abs_y;
    	long int abs_z;
    } absolute32;
    
    // ...
    
    {
    	absolute32 targetpos;
    
    	if (rapid)
    		{
    			fputc('N', outfile);
    			fwrite(&number, 1, sizeof(number), outfile); 
    			fputc('A', outfile);
    			printf("size A : %d\n", sizeof(targetpos)); // Debug -> 12
    			fwrite(&targetpos, 1, sizeof(targetpos), outfile); 
    		}
    	else
    		{
    			fputc('N', outfile);
    			fwrite(&number, 1, sizeof(number), outfile); 
    			fputc('B', outfile);
    			printf("size B : %d\n", sizeof(targetpos)); // Debug -> 12
    			fwrite(&targetpos, 1, sizeof(targetpos), outfile); 
    			fclose(outfile);	// Debug für Dateiabschluß
    		}
    }
    

    Das Ding schreibt entweder ein "A" oder ein "B" vor den Koordinatensatz. Während nach dem "A" wie erwartet 12 Bytes auf der Platte landen, sind es beim "B" 13 Bytes, es hängt immer eine Null an:

    0001 0203 0405 0607 0809 0A0B 0C0D 0E0F - 0123456789ABCDEF
    ----------------------------------------------------------------
    0x00: 4E02 0000 0054 014E 0300 0000 53E0 2E00 - N....T.N....Sà..
    0x10: 004E 0400 0000 411D 0000 0011 0000 00FB - .N....A........û
    0x20: FFFF FF4E 0500 0000 46F4 0500 004E 0500 - ÿÿÿN....Fô...N..
    0x30: 0000 421D 0000 0011 0000 000D 0A00 0000 - ..B.............
    

    Das tut es nur beim B- Kommando, ein "A"- Kommando ist ab 0x16 bis 0x22 zu sehen.
    Ganz gespenstisch auch 😮 : entferne ich "if" und "else", schreibt es den Koordinatensatz zweimal, was ich so zwar nicht brauchen kann, aber dann kommen beim "B" auch nur zwölf Bytes in die Datei.

    Ich weiß jetzt echt nicht, was ich probieren soll 😕 , aber vielleicht hat von euch jemand eine gute Idee! 🕶



  • Ist zwar nicht die Lösung, aber bei fwrite() sind der zweite und der dritte Parameter vertauscht:

    size_t fwrite(const void *ptr, size_t size, size_t  nitems, FILE *stream);
    

    was heißt:

    fwrite(&targetpos, sizeof(targetpos), 1, outfile);
    


  • +gjm+ schrieb:

    Ist zwar nicht die Lösung, aber bei fwrite() sind der zweite und der dritte Parameter vertauscht:

    Doch, ist die Lösung. Kaum macht mans richtig, schon gehts. Hab's vertauscht und jetzt kommen immer 12 Bytes.

    EDIT: Zu früh gefreut 😞 , um zwei soll man nimmer Debuggen, hatte vergessen, daß if und else noch auskommentiert waren. Wieder drin = 13 Bytes, altes Problem .. 🙄



  • um zwei soll man nimmer Debuggen

    Wann sonst?



  • zeig mal die aufrufe von fopen().



  • volkard schrieb:

    zeig mal die aufrufe von fopen().

    outfile = fopen("temp.m1", "w");
    	if (outfile)
    	{ // Variablen init usw
    

    Meinst Du wirklich, daß es daran liegen könnte?

    bgdnoy schrieb:

    Wann sonst?

    Nicht, wenn man seit sechs Uhr morgens schon dransaß. 😉 Da passieren dann die wirklichen Idiotenfehler. 🤡



  • pointercrash() schrieb:

    volkard schrieb:

    zeig mal die aufrufe von fopen().

    outfile = fopen("temp.m1", "w");
    	if (outfile)
    	{ // Variablen init usw
    

    Meinst Du wirklich, daß es daran liegen könnte?

    nein.aber ich wills auch nicht ausschließen. brauchte man für binärdateien nicht "wb"? ich glaub zwar, daß das "b" nur beim einlesen was bewirkt, aber in anbetracht der tatsache, daß es am gezeigten code nicht liegt, wird man bei den fehlervermutungen ausgelassener.



  • volkard schrieb:

    nein.aber ich wills auch nicht ausschließen. brauchte man für binärdateien nicht "wb"? ich glaub zwar, daß das "b" nur beim einlesen was bewirkt, aber in anbetracht der tatsache, daß es am gezeigten code nicht liegt, wird man bei den fehlervermutungen ausgelassener.

    Prima Idee, zumindest ist der kleine Dateiauszug jetzt richtig mit 12 Bytes je Satz in der Datei gelandet. 🙂 👍

    Also scheint es auch beim Schreiben einen Unterschied zu machen, ich suche noch nach einer Manpage, die das erklärt.

    Ein super- Danke ! 😃



  • Liegt tatsächlich an fopen() mit "w".

    0x20: FFFF FF4E 0500 0000 46F4 0500 004E 0500 - ÿÿÿN....Fô...N..
    0x30: 0000 421D 0000 0011 0000 00[b]0D 0A00 00[/b]00 - ..B.............
    

    Prüf mal ob im "B"-Datensatz die letzte Koordinate ein 0x0A enthält. fwrite() hat sie wahrscheinlich konvertiert in ein CRLF (0D0A).

    edit: Und die Länge von 13 kommt zustande, weil fwrite() ein Zeichen (0x0D) eingefügt hat:

    0x30: 0000 421D 0000 0011 0000 000D [b]0A00 0000[/b] - ..B.............
    


  • +gjm+ schrieb:

    Prüf mal ob im "B"-Datensatz die letzte Koordinate ein 0x0A enthält. fwrite() hat sie wahrscheinlich konvertiert in ein CRLF (0D0A).

    Pfeilgrad so war's! Das Blöde daran ist, daß ich in den meisten C-FAQs, manpages usw. kaum Hinweise auf den kleinen Unterschied gefunden habe, das wird meist unterschlagen, bzw. es wird kaum wo dezidiert auf die Folgen hingewiesen. Wenn nicht 0x0A letztes Byte der Struct ist, fällt es ja nicht auf ... fiese Sache 😞
    Aber mittlerweile kann ich das File ohne Fehler zurücklesen, heißt, ich muß mich nicht mehr damit befassen 🙂



  • Volkard hat's gewittert, aber seltsam, daß es keiner richtig erkannt hat.
    Es steht doch schon in deinem ersten Post in der letzten hexdump-Zeile:

    000D 0A00
    

    Vielleicht hab ich's wegen dem Leerzeichen übersehen?



  • bgdnoy schrieb:

    ...aber seltsam, daß es keiner richtig erkannt hat.

    es waren wohl nur linux-user anwesend. denen passiert sowas nicht.
    🙂


Anmelden zum Antworten