Daten aus Binärdatei in .pdf oder jpg. schreiben

Hallo Experte!

Ich habe mit einem Programm in C++ ein kleines Problem. Sinn ist es Daten, die über ein Netzwerk in einen Buffer geschrieben werden, an Hand ihrer Magic Number in das entsprechende Dateiformat zu schreiben. Nun habe ich die Daten in Binärdateien geschrieben, öffne diese, lese die Magic Number und versuche sie bspw. als PDF zu speichern. Nur der letzte Schritt funktioniert einfach nicht. Ich verwende die write() funktion im ofstream und öffne die neue Datei im binary mode. Aber die resultierende Datei lässt sich nicht öffnen, im Textedit kann ich sehen, dass nach einigen Zeilen Code einfach aufgehört wurde zu schreiben, obwohl der buffer lang genug war… Schicke ich eine txt Datei durch das Programm, funktioniert alles problemlos, der gesamte Inhalt wird in die neue Datei geschrieben. Allerdings haben txt Dateien ja keine Magic Number, also hilft mir das nicht besonders weiter. Hier ein Teil des Codes, der für das Problem interessant ist:

long size;
char * buffer;

std::ifstream in(filenames[i].c_str(),std::ios::in | std::ios::binary); //filenames include filename in .bin format
std::filebuf *pbuf;

pbuf=in.rdbuf();
size=pbuf->pubseekoff (0,std::ios::end,std::ios::in);
pbuf->pubseekpos (0,std::ios::in);

char magic1[12] = {0};
in.read(magic1, sizeof(magic1));

unsigned char magic[12] = {0};
for (int h = 0; hsgetn (buffer,size);
in.close();
myfile.write(buffer,size);
myfile.close();
delete[] buffer;
std::string temp2 = "open "; // hier wird die Datei über das Terminal geöffnet, was auch funktionieren würde, wenn die Datei nicht kaputt wäre
temp2.append(temp);
system(temp2.c_str());
}

Vielen Dank im Voraus für jede Art von Hinweis?

Hallo,

du arbeitest mit dem filebuf, den du mit pbuf=in.rdbuf(); holst. Woher weißt du, ob der groß genug ist für den Dateiinhalt. Die Größe, die du mittels size=pbuf->pubseekoff (0,std::ios::end,std::ios::in); bestimmst, ist die Größe des Puffers, nicht die Größe des Dateiinhalts.

Daher bricht die Übertragung nach Schreiben einer Buffergröße ab.

Noch ein Tipp: Mach mal ein using namespace std; - dann musst du nicht so viel std:: schreiben.

Viele Grüße
Holger

Hallo,

Danke für die schnelle Antwort!

Habe den filebuf mit

in.seekg(0,ifstream::end);
size=in.tellg();
in.seekg(0);

ersetzt. Das Problem bleibt jedoch leider das gleiche. Ich habe auch überprüft, ob ‚size‘ den richtigen Wert hat, was der Fall ist. Leider habe ich keine Ahnung, woran das Problem sonst noch liegen könnte…

Gruß,

Roboneko

Nun habe ich die Daten
in Binärdateien geschrieben, öffne diese, lese die Magic
Number und versuche sie bspw. als PDF zu speichern.

soweit im Quellcode sichtbar, handelt es sich einfach um ein ausprogrammiertes Kopieren einer Datei …

prüfe, ob korrekt kopiert wurde … (Filevergleich, Quelle-Ziel), wenn nein, dann passiert der Fehler beim Kopieren,
wenn ja, dann ist die Binärdatei (Quelle) schon fehlerhaft;

Hast du geprüft, ob pbuf->sgetn (buffer,size); die Größe zurückliefert?

Sonst sehe ich auch keinen Fehler. Du müsstest mal ein komplettes, compilierbares Programm schicken, welches auf ein Minimum reduziert ist - nicht nur ein Fragment.

Viele Grüße
Holger

hi,

für C++ bin ich kein Experte. Es hört sich allerdings so an, als kömmte es sich um ein synchronisationsproblem zwischen filebuffer und file handeln. probier doch mal explizit sync() aufzurufen bevor du die Datei schließt. Eigentlicht sollte der Aufruf close() allerdings den gleichen Effekt haben…

Hallo,
Du sagst im Textedit kannst Du sehen, dass die
Binärdatei nicht komplett geschreiben wurde. Zu einer Binärdatei können aber auch die berühmten textterminierenden 0en gehören…
Entsprcht denn die Größe der Datei nicht der erwarteten?

Aber die resultierende Datei lässt sich nicht
öffnen, im Textedit kann ich sehen, dass nach einigen Zeilen
Code einfach aufgehört wurde zu schreiben, obwohl der buffer
lang genug war…

Hallo,

du verwendest sgetn. Koennte es sein, dass in deiner Binaerdatei „zufaellilgerweise“ ein EOF enthalten ist?

Gruss
Andreas

streamsize sgetn ( char * s, streamsize n );

Get sequence of characters
Calls the protected virtual member xsgetn, which gets up to n characters from the input sequence and stores them in the array pointed by s.

If less than n characters are available in the input sequence the function returns all the available characters, as if successive calls to sbumpc were made until an EOF (or traits::eof() for other traits) was returned.

Hallo,

mein erster Blick fällt auf das char - Array. Wenn in Deinem Stream ein Null Byte ist, sollte das als Ende des char[] gewertet werden. Einfach mal im Debugger das char [] mit dem Binary vergleichen.

Viel Erfolg und Danke für ein Feedback.

Gerhard

Hallo,

klingt ja ein bischen nach der Neuerfindung des Rades …
und mit std::filebuf hab ich noch nie direkt gearbeitet, also nicht traurig sein, wenn ich jetzt Unsinn erzähle…

  1. Wie wird ‚size‘ bestimmt? Prüf mal ob der Wert im Programm richtig ist.
  2. Ich bin nicht sicher, ob pbuf->sgetn() auch auf Binärdaten arbeitet… -> Prüfen, ob danach in buffer die erwarteten Daten vorhanden sind.
  3. Ich persönlich würde in einer Schleife die Daten mit in.read() vom Input einlesen und mit out.write wegschreiben bis die Datei zu Ende ist. Ist nicht elegant, funktioniert aber.
  4. Warum der Umweg mit der magic number? Wenns geht, die Dateinamen mit übertragen, und die Daten binär rausschreiben, Dann funkioniert es mit allen Dateien.

Vielen Dank für die Hinweise. Es hat sich heraus gestellt, dass der Fehler wirklich schon früher passiert ist beim schreiben der Binärdatei. Habe deshalb das Program nochmal etwas umstrukturiert und jetzt läuft alles problemlos. Vielen Dank!

Danke für den Hinweis. Der Vergleich hat wirklich herausgebracht, dass der Fehler schon früher passiert ist. Jetzt funktioniert alles!

Hallo,

lang lang ist’s her… kann es sein das deine Routine ueber das erste 0x0 in buffer stolpert und der :write() Aufruf nur bis zum erstem 0x0 in buffer schreibt (Null-terminated string)?

Tschau
Peter

Howdy

Punkt 1:
Bitte Source Code mit pre tag so formatieren, dass man ihn lesen kann.

Punkt 2:

 pbuf-\>sgetn(buffer, size);

 //\>\>\>
 überprüf hier mal, ob das sgetn tatsächlich size zurückgibt. Es koennten
 auch weniger chars sein !!
 //


Punkt 3: bin derzeit auf Projekt in HH und O2 hat ein kleines Problem mit der mobilen Internetversorgung, kann also nicht immer schnell antworten.

Gruss
norsemanna

Probier mal, ob sich die Rohdatei mit dem folgenden Code (analog zu deinem) kopieren laesst.

size\_t copyfile(const char\* inputFileName, const char\* outputFileName)
{
 std::ifstream in(inputFileName, std::ios::in | std::ios::binary);
 std::ofstream out(outputFileName, std::ios::out | std::ios::binary);
 std::filebuf \*pbuf;
 const bool errorInfile = in.fail() || in.bad();
 const bool errorOutFile = out.fail() || out.bad();
 const size\_t size = 10240;

 char buffer[size];
 size\_t n = 0;
 size\_t bytes = 0;

 if (errorInfile || errorOutFile) {
 std::ostringstream message;

 in.close();
 out.close();

 if (errorInfile) {
 message sgetn(buffer, size);
 out.write(buffer, n);
 if (out.bad()) {
 throw std::runtime\_error("bad bit set in out.write");
 }

 bytes += n;
 } while (0 

Hallo, mit den stream-Funktionen programmiere ich nicht, ich verwende die stdio-Funktionen fread und fwrite zum Lesen und Schreiben von Dateien. Was mir an Deinem Code aufgefallen ist: Du verwendest einmal pbuf->pubseekpos und einmal in.seekg, was unterschiedliche Wirkung haben könnte.
Mein erster Verdacht war, dass Du eine Fuktion zum Lesen nutzt, die nur eine Zeile einliest, aber das ist bei sgetn wohl nicht der Fall, oder?
Viel Erfolg.

Hallo.

Einen Fehler kann ich auf die Schnelle auch nicht entdecken!
Besonders wo Du sagst, es geht mit Textdateien.
Aber ich würde einen Haufen Ausgaben einbauen, um den Fehler zu debuggen: ich hab den Code ein wenig ergänzt.
Falls Du weitere Fragen hast, nur zu. Wäre nett, wenn Du den Fehler mitteilen würdest.

Warum verwendest Du eigentlich den filebuf, statt direkt den ifstream zu lesen?

long size;
char * buffer;

std::ifstream in(filenames[i].c_str(),std::ios::in |
std::ios::binary); //filenames include filename in .bin format

if (!in) std::cout pubseekoff (0,std::ios::end,std::ios::in);
std::cout pubseekpos (0,std::ios::in);

char magic1[12] = {0};
in.read(magic1, sizeof(magic1));

unsigned char magic[12] = {0};
for (int h = 0; hsgetn (buffer,size);

std::cout

Hallo,
ich möchte mich entschuldigen, dass ich nicht „zeitnah“ geantwortet habe.
Die Anfrage muss bei mir untergegangen sein … ich hab sie jetzt erst zufällig in der Übersicht gesehen.

Ich gehe mal davon aus dass sich der Fall schon erledigt hat.

Ich würde davon ausgehen, dass im Stream ein bzw. mehrere Zeichen enthalten sind, welche mit den Char basierten Funktionen nicht gut gehen können (z.B. ein \0 oder ein EOF). Das ist bei Binärdaten durchaus korrekt, kann aber zu Problemen führen, wenn Funktionen verwendet werden, die eigentlich nur mit Textdateien umgehen (sgetn dürfte auch so ein Fall sein).
Abgesehen davon ist long für eine Dateigröße wohl in der aktuellen Zeit evtl. auch zu klein dimensioniert.