Binärdatei in C



  • Hi!

    Ich soll für eine Aufgabe eine Binärdatei erstellen und verwalten.

    Laut zahlreichen Internetseiten gibt man beim Öffnen mittels "wb" an, dass man die Daten binär speichern möchte.

    Habe dazu folgenden Code verwendet:

    FILE * pFile;
      char buffer[] = { 'x' , 'y' , 'z' };
      pFile = fopen ( "test.bin" , "wb" );
      fwrite (buffer , 1 , sizeof(buffer) , pFile );
      fclose (pFile);
    

    Wenn ich jetzt kompiliere und mein Programm starte, dann wird mir eine Datei "test.bin" angelegt aber wenn ich diese Daten mit dem Editor öffne kann ich darin "xyz" lesen.

    Ich dachte mit "wb" erzeuge ich Binärdaten in der Datei! Dann sollte ich ja eigentlich die Daten auch nicht lesen können? Diese Daten sollten ja nur mit einem Hex-Editor lesbar sein.

    Warum kann ich dann trotzdem "xyz" lesen in der Datei?

    Anscheinend habe ich hier etwas nicht richtig verstanden! Könnt ihr mir bitte dabei helfen?

    Lg, Domsi

    Ps: Verwende GCC Kompiler. Getestet unter Windows und unter Linux. Bei beiden das selbe Ergebnis!


  • Mod

    Was ist denn wohl die Binärdarstellung von "xyz"? Tipp: Diese Frage ist nicht schwer.

    Versuch stattdessen mal, ein paar Zahlen in die Datei zu schreiben.



  • Du machst den (üblichen) Fehler, unter Binärdatei eine Datei mit diesen vielen komischen Buchstaben, die kein Mensch lesen kann, zu verstehen.

    Was wird beim Abspeichern eines 'x' gemacht? Der ASCII-Wert wird in die Datei geschrieben. Und was macht der Editor? Er liest den ASCII-Wert ein und stellt ihn anhand der Tabelle dar.
    Die vielen komischen Zeichen in Binärdateien kommen daher, dass viele als char eingelesene Werte von Formaten wie jpg, mp3 etc. kleiner als 32 oder größer 127 sind und die Kombination der einzelnen Zeichen keinen Sinn ergibt -> für Menschen unlesbar.

    Schreib mal in einer Schleife viele Zufallszahlen in die Datei. Oder alle (char-) Werte von 0 bis 127.



  • Beim öffnen einer Binärdatei wird auch auf die Umsetzung einiger Steuerzeichen verzichtet.

    Da wäre der Zeilenvorschub '\n' (LF Line Feed) und der Wagenrücklauf '\r' (CR Carriage Return) bzw. die Kombination daraus.

    In Widows/DOS wird ein Zeilenende in einer Textdatei mit \r\n gekennzeichnet.
    Wird eine Datei im Textmodus geöffnet und es wird '\n' geschrieben dann macht DOS/Windows daraus ein \r\n. Beim lesen ist es umgekehrt.
    Im Binärmodus erfolg diese Umsetzung nicht.

    Siehe auch [url]http://de.wikipedia.org/wiki/Zeilenumbruch#ASCII
    [/url]



  • Ok gut es war gestern vermutlich einfach schon zu spät. Ist mir jetzt schon klar.

    Ich war einfach der Meinung in der Binärdatei stehen nur 0er und 1er 😉 Aber gut 🙂

    Aber mal eine andere Frage. Ich soll am Anfang der Datei eine positive Ganzzahl mit der Anzahl der eingegebenen Zeichen angeben.
    D.h. bei unsigned int auf 32bit habe ich 2^32 mögliche Zahlen

    Was ist nun aber der Grund, dass mir nur Zahlen bis 255 gespeichert werden?
    Wenn ich z.b. eine Zeichanzahl von 400

    unsigned int length = 400;
    

    und dies dann mir "frwite" in die Binärdatei schreibe dann steht "2" und "1" in der Datei??
    (Eingelesen hab ich mit fread und im Hex-Editor ist das selbe)

    Aber warum?? Ich kann ja genau bis 0-255 (2^8) eingeben, aber wieso? Wo wird mein int auf 2^8 begrenzt??

    Lg



  • Domsi schrieb:

    Wo wird mein int auf 2^8 begrenzt??

    Vermutlich bei deiner Lese- oder Schreiboperation. Du schreibst statt 4 oder 8 Bytes nur 1 Byte raus.

    Offtopic:
    Jetzt weiß ich endlich wozu 64Bit gut sind. Um die verwirrten Anfänger noch mehr verwirren zu können. 😃



  • Domsi schrieb:

    Ich war einfach der Meinung in der Binärdatei stehen nur 0er und 1er 😉 Aber gut 🙂

    aber doch! Nicht nur Dateien sondern alles, was Daten austauscht, haben außschließlich 0er und 1er. Wichtig ist ihre Darstellung, wie sie zu zusammengefasst werden und wie sie verstanden (= Darstellung) werden.



  • @supertux
    Ja ich weiß 😉 Ich bin eben davon ausgegangen dass die Darstellung dann 0er und 1er ist... wie gesagt war schon spät 😉

    @ Nick Unbekannt:

    Ok. Dachte ich gebe dass mit "sizof(nummer)" beim write an:

    unsigned int nummer = 400;
      pFile = fopen ( "test.bin" , "wb" );
      fwrite(&nummer, 1, sizeof(nummer), pFile);
    

    und was muss ich jetzt machen, damit die 400 drinnen steht??



  • Wieso, der Code ist doch richtig. Deine Leseoperation ist anscheinend falsch. Öffne die Datei doch einmal mit einem Hexeditor, dort sollte so etwas stehen:

    9001 0000
    nun die beiden Bytes und Wörter vertauschen (little endian)
    0000 0190
    entspricht dez. 1*16[h]2[/h]+9*16 = 256 + 144 = 400
    

    Edit: Bei fwrite hast du size und count verwechselt, dies spielt hier aber keine Rolle.



  • Ooookkkkk.

    Ich nehme dass jetzt einfach mal so hin.

    Wie kann ich jetzt 9001 0000
    richtig einlesen, damit wieder 400 als Ergebnis rauskommt?
    Muss ich dass nun auch so programmieren wie du es berechnet hast??



  • Nein, du liest die Daten genauso, wie du sie geschrieben hast. Die Rechnung war nur dafür da, damit du die Daten im Hexeditor richtig interpretieren kannst.



  • Genauso wie bei fwrite.

    unsigned int nummer;
    fread(&nummer,sizeof(nummer),1,pfile);
    

    Jetzt siehst du auch den Unterschied zu Text- und Binärmode.
    Wenn du jetzt z.B.: 2573 = 10*256+13 schreibst ist das \r\n.
    und beim lesen macht das System aus dem \n nochmal \r\n also \r\r\n 😞



  • Ok habe nun folgendes gemacht:

    unsigned int nummer;
    
      pFile = fopen ( "test.bin" , "rb" );
      fread(&nummer,sizeof(nummer),1,pFile);
      printf("Ergebnis: %d", nummer);
    

    Output:
    Ergebnis -1878982656

    was mache ich jetzt wieder falsch?



  • Machst du vielleicht so etwas?*

    unsigned int nummer = 400;
    pFile = fopen ( "test.bin" , "wb" );
    fwrite(&nummer, 1, sizeof(nummer), pFile); 	
    
    nummer = 0;
    pFile = fopen ( "test.bin" , "rb" );
    fread(&nummer,sizeof(nummer),1,pFile);
    printf("Ergebnis: %d", nummer);
    

    Du solltest geöffnete Dateien immer schließen und immer schauen, ob das Öffnen geklappt hat. Das Schließen einer geöffneten Datei funktioniert nicht automatisch.

    unsigned int nummer = 400;
    pFile = fopen ( "test.bin" , "wb" );
    if(pFile)
    {
      fwrite(&nummer, 1, sizeof(nummer), pFile); 	
      fclose(pFile);
    }
    nummer = 0;
    pFile = fopen ( "test.bin" , "rb" );
    if(pFile)
    {
      fread(&nummer,sizeof(nummer),1,pFile);
      printf("Ergebnis: %d", nummer);
      fclose(pFile);
    }
    

    Edit: Natürlich auf zwei Funktionen verteilt, die nacheinander aufgerufen werden.



  • unsigned int nummer;
    ...
    printf("Ergebnis: %d", nummer);
    

    Bei unsigned dann bitte %u (sollte bei 400 aber egal sein).
    Oder wenn du es beser lesen willst:

    printf("Ergebnis: %u %08x\n", nummer, nummer);
    

    Dann siehst du schon mal die Hex-Darstellung.



  • Ohhhh. Ups.

    Sorry mein Fehler. Ich hatte mit dem HEX-Editor das Binärfile verändert und wie ich es wieder in die Ursprungsform gebracht habe, habe ich einen fehler gemacht!

    Blöder Fehler... aber immerhin habe ich dank euch nun einiges über diese Materie gelernt 😉

    Danke an alle.



  • Mal eine andere Frage noch.

    Bei unsigned int (32 Bit) kann ich ja 4294967296 (2^32) Zahlen darstellen.

    Allerdings wenn ich:

    unsigned int nummer = 4294967295;
    

    Bekomme ich folgende Fehlermeldung:

    warning: this decimal constant is unsigned only in ISO C90

    Warum?? Ich es funktioniert nur wenn ich (429496729) also die letzte Stelle weglasse. Warum ist dies nur unter ISO C90 ... möglich?



  • Das ist eine Warnung.
    Der Compiler hat eine Fhelermöglichkeit erkannt und bittet dich doch mal genauer hinzuschauen.

    unsigned int nummer = 4294967295U;
    

    Durch das U teilst du dem Compiler mit das du ein unsigned int haben willst.



  • Ok und wie ist dass nun wenn dieser integer Wert erstellt wird?

    Also dieser Wert stellt die Länge des Textes dar. Die Länge ergibt sich einfach automatisch über eine Laufvariable.

    Wir bei so einer Laufvariable dieses U automatisch angehängt oder muss ich das exta machen?

    lg



  • Neeee. Wenn Du auf

    unsigned int nummer = 0;

    fortlaufend 1 (oder was auch immer) addierst, dann ist das völlig in Ordnung. Die Warnmeldung rührt einfach daher, daß die ausgeschriebene Zahl den Wertebereich eines int überschreitet. Mit dem U dahinter erkennt der Compiler, daß es sich um einen unsigned Wert handelt, der wiederum passt in 32 bit hinein.


Log in to reply