Binär Datei "erstellen"

Vom einfachen Programm zum fertigen Debian-Paket, Fragen rund um Programmiersprachen, Scripting und Lizenzierung.
Antworten
EmanuelBennici
Beiträge: 19
Registriert: 29.07.2017 16:36:14

Binär Datei "erstellen"

Beitrag von EmanuelBennici » 06.10.2017 13:20:10

Hey,
ich würde gerne aus mehreren Dateien (.xml & .pdf) eine .bin Datei machen,
Also so wie es Git auch macht wenn man ein Commit seinen projektes erstellt,
Git macht dann aus der Projekt Repository eine .bin Datei.
Und kann auch diese wieder umwandeln.

Ich würde gerne dies auch in mein C programm implementieren.

Wie könnte ich das machen?

Benutzeravatar
TRex
Moderator
Beiträge: 8318
Registriert: 23.11.2006 12:23:54
Wohnort: KA

Re: Binär Datei "erstellen"

Beitrag von TRex » 06.10.2017 13:25:58

nimm tar (ja, davon gibts auch ne C-API).
Jesus saves. Buddha does incremental backups.
Windows ist doof, Linux funktioniert nichtDon't break debian!Wie man widerspricht

EmanuelBennici
Beiträge: 19
Registriert: 29.07.2017 16:36:14

Re: Binär Datei "erstellen"

Beitrag von EmanuelBennici » 06.10.2017 13:47:23

Ich möchte allerdings das System dahinter verstehen!
Ich möchte nicht die tar API verwenden!!
:)

Benutzeravatar
MSfree
Beiträge: 11605
Registriert: 25.09.2007 19:59:30

Re: Binär Datei "erstellen"

Beitrag von MSfree » 06.10.2017 14:13:42

EmanuelBennici hat geschrieben: ↑ zum Beitrag ↑
06.10.2017 13:47:23
Ich möchte allerdings das System dahinter verstehen!
bin ist kein Dateiformat, es kann also auch kein System dahinter stecken. Das einzige, was halbwegs gesichert ist, ist, daß in einer bin-Datei nicht nur ASCII-Daten stecken sondern beliebige Binärdaten.

Da du gerade GIT genannt hast, so ist "bin" im Sinne von GIT sicherlich etwas völlig anderes als das, was du willst. GIT ist ein Revisionskontrollsystem und speichert verschiedene Dateiversionen als Differenz zwischen zwei Versionen ab. Als Zusatzinformationen zum eigentlichen Dateiinhalt werden Versionsnummern, Branchinformationen, Längeninformationen des Datenblocks und diverse Zeitstempel mitgeführt.

Das, was du willst, ist nur das Hintereinanderhängen von zwei willkührlichen Dateien. Dazu muß man in das "bin" nur Dateiname, und Größe der ursprünlichen Datei und den Inhalt in ein beliebiges Archivformat speichern. Das Format kanst du dir selbst ausdenken oder aber z.B. auf tar zurückgreifen.

pferdefreund
Beiträge: 3799
Registriert: 26.02.2009 14:35:56

Re: Binär Datei "erstellen"

Beitrag von pferdefreund » 06.10.2017 19:38:51

Wenn es in C implementiert werden soll, dann mit stat Größe ermitteln,
workbereich mit malloc erstellen, mit fopen ("datei","rb") Dateieni zum lesen schreiben("wb")(ausgabe) binär öffnen,Header ausgeben mit Länge, und was es ist, binär gelesen Datei mit fwrite schreiben,
nächste Datei das selbe Spiel, bis alle abgearbeitet sind. Rausholen - selbes Verfahren - nur umgedreht. Sollte sich auch anstatt in C mit gnucobol realisieren lassen - da kann man auch binär lesen und schreiben. Andere Sprachen gehen sicherlich auch...

Benutzeravatar
Meillo
Moderator
Beiträge: 9230
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Binär Datei "erstellen"

Beitrag von Meillo » 06.10.2017 21:53:33

pferdefreund hat geschrieben: ↑ zum Beitrag ↑
06.10.2017 19:38:51
Wenn es in C implementiert werden soll, dann mit stat Größe ermitteln,
workbereich mit malloc erstellen, mit fopen ("datei","rb") Dateieni zum lesen schreiben("wb")(ausgabe) binär öffnen,Header ausgeben mit Länge, und was es ist, binär gelesen Datei mit fwrite schreiben,
nächste Datei das selbe Spiel, bis alle abgearbeitet sind. Rausholen - selbes Verfahren - nur umgedreht. Sollte sich auch anstatt in C mit gnucobol realisieren lassen - da kann man auch binär lesen und schreiben. Andere Sprachen gehen sicherlich auch...
In Unix sind binaeres und textuelles Lesen und Schreiben identisch:
Manpage fopen(3) hat geschrieben: The mode string can also include the letter 'b' either as
a last character or as a character between the characters
in any of the two-character strings described above.
This is strictly for compatibility with C89 and has no
effect; the 'b' is ignored on all POSIX conforming sys-
tems, including Linux. (Other systems may treat text
files and binary files differently, and adding the 'b'
may be a good idea if you do I/O to a binary file and
expect that your program may be ported to non-UNIX envi-
ronments.)
Die einzige Voraussetzung fuer das Schreiben und Lesen von binaeren Dateien ist die Faehigkeit mit Null-Bytes umgehen zu koennen.


Das Ziel des Fragenden war ja, zu verstehen wie man beliebige Dateien in eine einzige verbindet. (Ob binaer oder nicht ist fuer mich als Unixer egal, weil auf Unix gilt: All data is text.) Jedenfalls fallen mir dazu zwei Verfahren ein:

1) Man speichert sich die Laenge des folgenden Dateisegments plus evtl. weitere Metadaten in einem Header und anschliessend den Inhalt der Einzeldatei selbst. Dann der naechste Header mit Laengenangabe und daran anschliessend wieder ein Dateiinhalt, usw. (So scheint mir das tar zu machen.) Alternativ koennte man alle Laengen gleich zu Beginn ablegen.

2) Man haengt alle Dateisegmente aneinander, getrennt durch irgendwelche eindeutingen Trenndaten (die man folglich in den Dateisegmenten escapen muesste, falls sie darin vorkommen wuerden. (Das ist der mbox-Ansatz.)

Der Ansatz 1 ist einfacher weil man nichts escapen muss und zusaetzliche Metainformationen (wie den Namen der Einzeldatei) transportieren kann. Das zu implementieren ist sehr einfach. Probier's aus!
Use ed once in a while!

pferdefreund
Beiträge: 3799
Registriert: 26.02.2009 14:35:56

Re: Binär Datei "erstellen"

Beitrag von pferdefreund » 09.10.2017 12:05:14

Na ja, das mit dem "b" beim Open stimmt für Unix - aber wenn man es macht, schadet es nix und es ist auch noch portabel.
Eventuell will ich ja sowas auch mal auf nem Mac, Windows, Meyer oder Müller machen.

Benutzeravatar
MSfree
Beiträge: 11605
Registriert: 25.09.2007 19:59:30

Re: Binär Datei "erstellen"

Beitrag von MSfree » 09.10.2017 12:15:14

Meillo hat geschrieben: ↑ zum Beitrag ↑
06.10.2017 21:53:33
In Unix sind binaeres und textuelles Lesen ... identisch:
Nein, spätestens, wenn ein Ctrl-D im Datenstrom ist, wird das beim textuellen Lesen als EOF aufgefaßt.

Benutzeravatar
Meillo
Moderator
Beiträge: 9230
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Binär Datei "erstellen"

Beitrag von Meillo » 09.10.2017 13:39:59

MSfree hat geschrieben: ↑ zum Beitrag ↑
09.10.2017 12:15:14
Meillo hat geschrieben: ↑ zum Beitrag ↑
06.10.2017 21:53:33
In Unix sind binaeres und textuelles Lesen ... identisch:
Nein, spätestens, wenn ein Ctrl-D im Datenstrom ist, wird das beim textuellen Lesen als EOF aufgefaßt.
Wie sieht denn Ctrl-D binaer aus? Also zeig mir mal einen Hexdump von einer Datei mit einem Ctrl-D drin.

Ich denke, du bringst da was durcheinander, denn ^D ist ein Feature deines Terminals (siehe `eof' in stty(1)).

Lesen in Unix (dem Kernel) passiert nur auf einem Wege, naemlich mittels read(2). Dort gibt es keine Unterscheidung zwischen binaer und textuell. Klar, du kannst mit Stringfunktionen wie fgets(3) nicht binaer lesen ... aber auch nur aus dem einen Grund, weil dort keine Null-Bytes verarbeitet werden koennen. Und das ist AFAIK die einzige Einschraenkung.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9230
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Binär Datei "erstellen"

Beitrag von Meillo » 09.10.2017 13:40:15

pferdefreund hat geschrieben: ↑ zum Beitrag ↑
09.10.2017 12:05:14
Na ja, das mit dem "b" beim Open stimmt für Unix - aber wenn man es macht, schadet es nix und es ist auch noch portabel.
Eventuell will ich ja sowas auch mal auf nem Mac, Windows, Meyer oder Müller machen.
Ja.
Use ed once in a while!

Benutzeravatar
MSfree
Beiträge: 11605
Registriert: 25.09.2007 19:59:30

Re: Binär Datei "erstellen"

Beitrag von MSfree » 09.10.2017 14:02:15

Meillo hat geschrieben: ↑ zum Beitrag ↑
09.10.2017 13:39:59
Wie sieht denn Ctrl-D binaer aus?
Dez: 4, Hex: 0x04
Also zeig mir mal einen Hexdump von einer Datei mit einem Ctrl-D drin.
0x04 0x41 0x42 0x4C 0x4D

Ich habe das jetzt aber nicht weiter ausprobiert, gut möglich, daß das auch gefressen wird. Unter DOS war es früher jedenfalls üblich, daß dort nur bis zum nächsten Ctrl-Z gelesen wurde und DOS End-of-Line anders interprätiert als Linux.
Klar, du kannst mit Stringfunktionen wie fgets(3) nicht binaer lesen ... aber auch nur aus dem einen Grund, weil dort keine Null-Bytes verarbeitet werden koennen.
fgets versucht, bis zum nächsten Nullbyte zu lesen. Wenn du dort einen 10GBYte Straem ohne eine einzige Null reinfütterst, gibt es dicke Backen oder ein SigSeg.

Benutzeravatar
Meillo
Moderator
Beiträge: 9230
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Binär Datei "erstellen"

Beitrag von Meillo » 09.10.2017 15:42:49

MSfree hat geschrieben: ↑ zum Beitrag ↑
09.10.2017 14:02:15
Meillo hat geschrieben: ↑ zum Beitrag ↑
09.10.2017 13:39:59
Wie sieht denn Ctrl-D binaer aus?
Dez: 4, Hex: 0x04
Also zeig mir mal einen Hexdump von einer Datei mit einem Ctrl-D drin.
0x04 0x41 0x42 0x4C 0x4D

Ich habe das jetzt aber nicht weiter ausprobiert, gut möglich, daß das auch gefressen wird. Unter DOS war es früher jedenfalls üblich, daß dort nur bis zum nächsten Ctrl-Z gelesen wurde und DOS End-of-Line anders interprätiert als Linux.
Hier der Praxistest, eine Datei mit einem 0x04 drin und cat(1) kann sie auslesen:

Code: Alles auswählen

:-Q od -c <file.bin 
0000000   f   o   o  \n 004  \n   b   a   r  \n
0000012

:-Q cat file.bin 
foo

bar

:-Q cat <file.bin | od -c      
0000000   f   o   o  \n 004  \n   b   a   r  \n
0000012

:-Q 
Nun kann man natuerlich sagen, dass cat(1) vermutlich binaer arbeitet und nicht textuell. Nun gut, dann halt mit diesem C-Programm, das ich mal schnell hingeklopft habe:

Code: Alles auswählen

:-Q cat reader.c
#include <stdio.h>

int
main()
{
        char s[10];
        while (fgets(s, sizeof(s), stdin)) {
                fputs(s, stdout);
        }
        if (!feof(stdin)) {
                /* not sure if correct */
                perror(NULL);
        }
        return 0;
}


:-Q make reader 
cc     reader.c   -o reader

:-Q ./reader <file.bin | od -c
0000000   f   o   o  \n 004  \n   b   a   r  \n
0000012

:-Q 
Siehe da: fgets(3) und fputs(3) lesen 0x4 ganz problemlos.

MSfree hat geschrieben: ↑ zum Beitrag ↑
09.10.2017 14:02:15
Klar, du kannst mit Stringfunktionen wie fgets(3) nicht binaer lesen ... aber auch nur aus dem einen Grund, weil dort keine Null-Bytes verarbeitet werden koennen.
fgets versucht, bis zum nächsten Nullbyte zu lesen. Wenn du dort einen 10GBYte Straem ohne eine einzige Null reinfütterst, gibt es dicke Backen oder ein SigSeg.
Nein:
Manpage fgets(3) hat geschrieben: char *fgets(char *s, int size, FILE *stream);

fgets() reads in at most one less than size characters
from stream and stores them into the buffer pointed to by
s. Reading stops after an EOF or a newline. If a new‐
line is read, it is stored into the buffer. A terminat‐
ing null byte ('\0') is stored after the last character
in the buffer.
AFAIK kann fgets(3) sogar Null-Bytes lesen, bloss wird das Ergebnis in einen C-String gespeichert, so dass dieser per Definition am ersten Null-Byte endet. Man hat auch keine Moeglichkeit die tatsaechliche Anzahl an gelesenen Bytes zu erfahren um den String als binaeres Char-Array zu verarbeiten. Auch kann fputs(3) keine Null-Bytes ausgeben.
Use ed once in a while!

Benutzeravatar
Meillo
Moderator
Beiträge: 9230
Registriert: 21.06.2005 14:55:06
Wohnort: Balmora
Kontaktdaten:

Re: Binär Datei "erstellen"

Beitrag von Meillo » 09.10.2017 23:10:51

Meillo hat geschrieben: ↑ zum Beitrag ↑
09.10.2017 13:39:59
Klar, du kannst mit Stringfunktionen wie fgets(3) nicht binaer lesen ... aber auch nur aus dem einen Grund, weil dort keine Null-Bytes verarbeitet werden koennen.
Meillo hat geschrieben: ↑ zum Beitrag ↑
09.10.2017 15:42:49
AFAIK kann fgets(3) sogar Null-Bytes lesen, bloss wird das Ergebnis in einen C-String gespeichert, so dass dieser per Definition am ersten Null-Byte endet. Man hat auch keine Moeglichkeit die tatsaechliche Anzahl an gelesenen Bytes zu erfahren um den String als binaeres Char-Array zu verarbeiten. Auch kann fputs(3) keine Null-Bytes ausgeben.

Es geht doch, mit fgets(3) binaer zu lesen, wenn man ein bisschen rumtrickst:

Code: Alles auswählen

:-Q cat reader2.c
#include <stdio.h>
#include <string.h>

int
main()
{
        char s[10];
        char *cp;

        while (fgets(s, sizeof(s), stdin)) {
                cp = memchr(s, '\n', sizeof(s));
                fwrite(s, (cp ? cp-s+1 : sizeof(s)-1), 1, stdout);
        }
        if (!feof(stdin)) {
                perror(NULL);
        }
        return 0;
}


:-Q make reader2
cc     reader2.c   -o reader2

:-Q <file.bin tr '\04' '\0' | ./reader2 | od -c
0000000   f   o   o  \n  \0  \n   b   a   r  \n
0000012

:-Q 
Bloss mit fputs(3) binaer zu schreiben, das geht wirklich nicht. (Edit: ... aus dem einzigen Grund, dass es keine Null-Bytes ausgeben kann.)
Use ed once in a while!

Antworten