Lesen und Schreiben in Binärdateien in C?

Lesezeit: 9 Minuten

Benutzeravatar von user1257114
Benutzer1257114

Hat jemand ein Beispiel für Code, der in eine Binärdatei schreiben kann. Und auch Code, der eine Binärdatei lesen und auf dem Bildschirm ausgeben kann. Wenn ich mir Beispiele anschaue, kann ich in eine Datei schreiben, aber wenn ich versuche, aus einer Datei zu lesen, wird sie nicht korrekt ausgegeben.

  • Kannst du deinen Code zeigen?

    – Chrisaycock

    11. Juli 2013 um 16:21 Uhr

  • Das Internet wird viele Beispiele haben. Wie gibst du die Daten aus? Vielleicht ist das falsch.

    – Arztliebe

    11. Juli 2013 um 16:23 Uhr

Mikes Benutzeravatar
Mike

Das Lesen und Schreiben von Binärdateien ist so ziemlich dasselbe wie jede andere Datei, der einzige Unterschied besteht darin, wie Sie sie öffnen:

unsigned char buffer[10];
FILE *ptr;

ptr = fopen("test.bin","rb");  // r for read, b for binary

fread(buffer,sizeof(buffer),1,ptr); // read 10 bytes to our buffer

Sie sagten, Sie können es lesen, aber es wird nicht korrekt ausgegeben … denken Sie daran, dass Sie bei der “Ausgabe” dieser Daten kein ASCII lesen, also ist es nicht so, als würde man eine Zeichenfolge auf dem Bildschirm drucken:

for(int i = 0; i<10; i++)
    printf("%u ", buffer[i]); // prints a series of bytes

Das Schreiben in eine Datei ist ziemlich gleich, mit der Ausnahme, dass Sie verwenden fwrite() Anstatt von fread():

FILE *write_ptr;

write_ptr = fopen("test.bin","wb");  // w for write, b for binary

fwrite(buffer,sizeof(buffer),1,write_ptr); // write 10 bytes from our buffer

Da wir über Linux sprechen, gibt es eine einfache Möglichkeit, eine Plausibilitätsprüfung durchzuführen. Installieren hexdump auf Ihrem System (falls es noch nicht dort ist) und sichern Sie Ihre Datei:

mike@mike-VirtualBox:~/C$ hexdump test.bin
0000000 457f 464c 0102 0001 0000 0000 0000 0000
0000010 0001 003e 0001 0000 0000 0000 0000 0000
...

Vergleichen Sie das jetzt mit Ihrer Ausgabe:

mike@mike-VirtualBox:~/C$ ./a.out 
127 69 76 70 2 1 1 0 0 0

hm, vielleicht änderst du das printf zu einem %x um das etwas klarer zu machen:

mike@mike-VirtualBox:~/C$ ./a.out 
7F 45 4C 46 2 1 1 0 0 0

Guck mal! Die Daten stimmen jetzt überein*. Großartig, wir müssen die Binärdatei richtig lesen!

* Beachten Sie, dass die Bytes am Ausgang nur vertauscht werden, aber dass die Daten korrekt sind, Sie können diese Art von Dingen anpassen

  • Ich weiß, ist alt, aber es gibt einige Fragen, die ich stellen muss: “// 10 Bytes in unseren Puffer schreiben” bedeutet, dass das, was sich in Ihrem Puffer befindet, in Ihrer Datei gespeichert wird?

    – Mager

    19. Mai 2016 um 22:46 Uhr

  • @Gaunt – Ja, ich hätte “von” sagen sollen, um das klarer zu machen; Ich habe das jetzt behoben. In diesem Beispiel gehe ich davon aus, dass “buffer” existiert und mit einigen Daten gefüllt ist, die in “test.bin” geschrieben werden, wie von gezeigt wird write_ptr. Wenn Sie das ausführen, können Sie die Datei test.bin “hexdumpen” und diese Bytes darin sehen.

    – Mike

    24. Mai 2016 um 12:56 Uhr

  • Beachten Sie, dass unter Linux (und auf Unix-basierten Systemen im Allgemeinen) die b flag ist ‘optional’ — auf solchen Systemen wird nicht zwischen einer Binärdatei und einer Textdatei unterschieden. Der Unterschied ist jedoch unter Windows sehr wichtig. Wenn Ihr Code Anspruch auf Portabilität hat, fügen Sie die hinzu b wenn Sie die Datei als Binärdatei behandeln.

    – Jonathan Leffler

    24. März 2017 um 17:12 Uhr


  • Vergiss es nicht fclose(ptr);!

    Benutzer376845

    13. Dezember 2017 um 15:14 Uhr

  • Im Binärmodus schon fread Funktion Lesevorgang beenden, während CR- oder LF-Zeichen gefunden wurden?

    – Scheff

    25. November 2020 um 17:37 Uhr

Benutzeravatar von Alan Corey
Alan Corey

Es gibt ein paar Möglichkeiten, dies zu tun. Wenn ich binär lesen und schreiben möchte, verwende ich normalerweise open(), read(), write(), close(). Was völlig anders ist, als ein Byte nach dem anderen zu tun. Sie arbeiten mit ganzzahligen Dateideskriptoren statt mit FILE * -Variablen. fileno erhält einen Integer-Deskriptor von einem FILE * BTW. Sie lesen einen Puffer voller Daten, sagen wir 32k Bytes auf einmal. Der Puffer ist wirklich ein Array, aus dem Sie sehr schnell lesen können, da es sich im Speicher befindet. Und das gleichzeitige Lesen und Schreiben vieler Bytes ist schneller als eines nach dem anderen. Es heißt Blockread in Pascal, glaube ich, aber read() ist das C-Äquivalent.

Ich habe nachgesehen, aber ich habe keine Beispiele zur Hand. OK, diese sind nicht ideal, weil sie auch Sachen mit JPEG-Bildern machen. Hier ist eine Lektüre, Sie interessieren sich wahrscheinlich nur für den Teil von open() bis close(). fbuf ist das Array, in das gelesen werden soll, sb.st_size ist die Dateigröße in Bytes von einem stat()-Aufruf.

    fd = open(MASKFNAME,O_RDONLY);
    if (fd != -1) {
      read(fd,fbuf,sb.st_size);
      close(fd);
      splitmask(fbuf,(uint32_t)sb.st_size); // look at lines, etc
      have_mask = 1;
    }

Hier ist ein Schreibvorgang: (hier ist pix das Byte-Array, jwidth und jheight sind die JPEG-Breite und -Höhe, also schreiben wir für RGB-Farben Höhe * Breite * 3 Farbbytes). Es ist die Anzahl der zu schreibenden Bytes.

void simpdump(uint8_t *pix, char *nm) { // makes a raw aka .data file
  int sdfd;
  sdfd = open(nm,O_WRONLY | O_CREAT);
  if (sdfd == -1) {
    printf("bad open\n");
    exit(-1);
  }
  printf("width: %i height: %i\n",jwidth,jheight);  // to the console
  write(sdfd,pix,(jwidth*jheight*3));
  close(sdfd);
}

Blick auf Mann 2 öffnen, auch lesen, schreiben, schließen. Auch dieses JPEG-Beispiel im alten Stil.c: https://github.com/LuaDist/libjpeg/blob/master/example.c Ich lese und schreibe hier ein ganzes Bild auf einmal. Aber sie sind binäre Lese- und Schreibvorgänge von Bytes, nur eine Menge auf einmal.

“Aber wenn ich versuche, aus einer Datei zu lesen, wird sie nicht korrekt ausgegeben.” Hmmm. Wenn Sie eine Zahl 65 lesen, ist das (dezimal) ASCII für ein A. Vielleicht sollten Sie sich auch man ascii ansehen. Wenn Sie eine 1 wollen, ist das ASCII 0x31. Eine char-Variable ist wirklich eine winzige 8-Bit-Ganzzahl. Wenn Sie ein printf als %i ausführen, erhalten Sie den ASCII-Wert, wenn Sie ein %c ausführen, erhalten Sie das Zeichen. Führen Sie %x für hexadezimal aus. Alle von der gleichen Nummer zwischen 0 und 255.

Ich bin ziemlich zufrieden mit meiner Lösung “Erstelle ein schwaches Pin-Speicherprogramm”. Vielleicht hilft es Leuten, die ein sehr einfaches IO-Beispiel für eine Binärdatei benötigen, dem sie folgen können.

$ ls
WeakPin  my_pin_code.pin  weak_pin.c
$ ./WeakPin
Pin: 45 47 49 32
$ ./WeakPin 8 2
$ Need 4 ints to write a new pin!
$./WeakPin 8 2 99 49
Pin saved.
$ ./WeakPin
Pin: 8 2 99 49
$
$ cat weak_pin.c
// a program to save and read 4-digit pin codes in binary format

#include <stdio.h>
#include <stdlib.h>

#define PIN_FILE "my_pin_code.pin"

typedef struct { unsigned short a, b, c, d; } PinCode;


int main(int argc, const char** argv)
{
    if (argc > 1)  // create pin
    {
        if (argc != 5)
        {
            printf("Need 4 ints to write a new pin!\n");
            return -1;
        }
        unsigned short _a = atoi(argv[1]);
        unsigned short _b = atoi(argv[2]);
        unsigned short _c = atoi(argv[3]);
        unsigned short _d = atoi(argv[4]);
        PinCode pc;
        pc.a = _a; pc.b = _b; pc.c = _c; pc.d = _d;
        FILE *f = fopen(PIN_FILE, "wb");  // create and/or overwrite
        if (!f)
        {
            printf("Error in creating file. Aborting.\n");
            return -2;
        }

        // write one PinCode object pc to the file *f
        fwrite(&pc, sizeof(PinCode), 1, f);  

        fclose(f);
        printf("Pin saved.\n");
        return 0;
    }

    // else read existing pin
    FILE *f = fopen(PIN_FILE, "rb");
    if (!f)
    {
        printf("Error in reading file. Abort.\n");
        return -3;
    }
    PinCode pc;
    fread(&pc, sizeof(PinCode), 1, f);
    fclose(f);

    printf("Pin: ");
    printf("%hu ", pc.a);
    printf("%hu ", pc.b);
    printf("%hu ", pc.c);
    printf("%hu\n", pc.d);
    return 0;
}
$

Dies ist ein Beispiel zum Lesen und Schreiben von binären jjpg- oder wmv-Videodateien. DATEI *fout; DATEI *fin;

Int ch;
char *s;
fin=fopen("D:\\pic.jpg","rb");
if(fin==NULL)
     {  printf("\n Unable to open the file ");
         exit(1);
      }

 fout=fopen("D:\\ newpic.jpg","wb");
 ch=fgetc(fin);
       while (ch!=EOF)
             { 
                  s=(char *)ch;
                  printf("%c",s);
                 ch=fgetc (fin):
                 fputc(s,fout);
                 s++;
              }

        printf("data read and copied");
        fclose(fin);
        fclose(fout);

Ich hatte wirklich Mühe, einen Weg zu finden, eine Binärdatei in ein Byte-Array in C++ einzulesen, das die gleichen Hex-Werte ausgeben würde, die ich in einem Hex-Editor sehe. Nach langem Ausprobieren scheint dies der schnellste Weg zu sein, dies ohne zusätzliche Casts zu tun. Standardmäßig lädt es die gesamte Datei in den Speicher, druckt aber nur die ersten 1000 Bytes.

string Filename = "BinaryFile.bin";
FILE* pFile;
pFile = fopen(Filename.c_str(), "rb");
fseek(pFile, 0L, SEEK_END);
size_t size = ftell(pFile);
fseek(pFile, 0L, SEEK_SET);
uint8_t* ByteArray;
ByteArray = new uint8_t[size];
if (pFile != NULL)
{
    int counter = 0;
    do {
        ByteArray[counter] = fgetc(pFile);
        counter++;
    } while (counter <= size);
    fclose(pFile);
}
for (size_t i = 0; i < 800; i++) {
    printf("%02X ", ByteArray[i]);
}

Benutzeravatar von Yasen
Jasen

Diese Frage ist verknüpft mit der Frage How to write binary data file on C and plot it using Gnuplot by CAMILO HG. Ich weiß, dass das eigentliche Problem aus zwei Teilen besteht: 1) Schreiben Sie die binäre Datendatei, 2) Plotten Sie sie mit Gnuplot.

Der erste Teil wurde hier sehr klar beantwortet, also habe ich nichts hinzuzufügen.

Zweitens ist der einfache Weg, die Leute zum Gnuplot-Handbuch zu schicken, und ich sicher, dass jemand eine gute Antwort findet, aber ich finde sie nicht im Web, also werde ich eine Lösung erklären (die in der realen sein muss Frage, aber ich bin neu in Stackoverflow und kann dort nicht antworten):

Nachdem Sie Ihre binäre Datendatei mit geschrieben haben fwrite(), sollten Sie ein sehr einfaches Programm in C erstellen, einen Reader. Der Reader enthält nur die gleiche Struktur wie der Writer, aber Sie verwenden fread() stattdessen fwrite(). Es ist also sehr einfach, dieses Programm zu generieren: Kopieren Sie in die reader.c archivieren Sie den schreibenden Teil Ihres ursprünglichen Codes und ändern Sie schreiben für lesen (und “wb” für “rb”). Darüber hinaus könnten Sie einige Überprüfungen für die Daten einbauen, zum Beispiel, ob die Länge der Datei korrekt ist. Und schließlich muss Ihr Programm die Daten in der Standardausgabe mit a ausgeben printf().

Um es klar zu sagen: Ihr Programm läuft so ab

$ ./reader data.dat

X_position Y_position  (it must be a comment for Gnuplot)*

1.23 2.45

2.54 3.12

5.98 9.52

Okey, mit diesem Programm müssen Sie in Gnuplot nur die Standardausgabe des Readers an Gnuplot leiten, etwa so:

plot '< ./reader data.dat'

Diese Zeile führt das Programm reader aus, und die Ausgabe wird mit Gnuplot verbunden und es zeichnet die Daten.

*Da Gnuplot die Ausgabe des Programms lesen wird, müssen Sie wissen, was Gnuplot lesen und darstellen kann und was nicht.

1418850cookie-checkLesen und Schreiben in Binärdateien in C?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy