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.
Lesen und Schreiben in Binärdateien in C?
Benutzer1257114
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 hinzub
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
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]);
}
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.
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