Binärdatei lesen und schreiben

103

Ich versuche, Code zu schreiben, um eine Binärdatei in einen Puffer zu lesen, und dann den Puffer in eine andere Datei zu schreiben. Ich habe den folgenden Code, aber der Puffer speichert nur ein paar ASCII-Zeichen aus der ersten Zeile in der Datei und sonst nichts.

int length;
char * buffer;

ifstream is;
is.open ("C:\\Final.gif", ios::binary );
// get length of file:
is.seekg (0, ios::end);
length = is.tellg();
is.seekg (0, ios::beg);
// allocate memory:
buffer = new char [length];
// read data as a block:
is.read (buffer,length);
is.close();

FILE *pFile;
pFile = fopen ("C:\\myfile.gif", "w");
fwrite (buffer , 1 , sizeof(buffer) , pFile );
nf313743
quelle
28
Sie sollten sich für die Behandlung von iostream- oder C-Dateien entscheiden. Bitte verwenden Sie nicht beide.
Braten

Antworten:

172

Wenn Sie dies auf C ++ - Weise tun möchten, gehen Sie folgendermaßen vor:

#include <fstream>
#include <iterator>
#include <algorithm>

int main()
{
    std::ifstream input( "C:\\Final.gif", std::ios::binary );
    std::ofstream output( "C:\\myfile.gif", std::ios::binary );

    std::copy( 
        std::istreambuf_iterator<char>(input), 
        std::istreambuf_iterator<char>( ),
        std::ostreambuf_iterator<char>(output));
}

Wenn Sie diese Daten in einem Puffer benötigen, um sie oder etwas anderes zu ändern, gehen Sie folgendermaßen vor:

#include <fstream>
#include <iterator>
#include <vector>

int main()
{
    std::ifstream input( "C:\\Final.gif", std::ios::binary );

    // copies all data into buffer
    std::vector<unsigned char> buffer(std::istreambuf_iterator<char>(input), {});

}
Björn Pollex
quelle
4
Was ist, wenn ich nur einen Teil des Datenspeichers in den Puffer kopieren möchte? Wie kann ich es tun? Sagen wir 1024 Bytes.
wie
8
@Mikhail Hier finden Sie einige Benchmarking.
Paolo M
3
AFAIK, Binärdateien enthalten manchmal unlesbare Zeichen, in der Tat sind sie überhaupt keine Zeichen. Ist dieser Code sicher zum Lesen von Nicht-Text-Basisdateien? Mein Wissen ist in diesem Bereich kurz :)
Andiana
5
Sogenannt charwird in C / C ++ zum Speichern von Bytes verwendet (und das schon seit 40 Jahren). es ist sicher so, so lange zu tun , wie Sie versuchen , nicht wirklich USE , dass die Daten als Zeichen (nicht strlen () verwenden Sie darauf nicht , es drucken zu trösten, etc). c ++ 17 führt std::bytezu diesem Zweck ein (was eigentlich immer noch charin Verkleidung ist)
d.Candela
2
@DavidTran Kann nicht sagen, ohne mehr zu wissen - dies scheint, als sollten Sie ein minimales Beispiel erstellen, das das Problem reproduziert, und dann eine Frage stellen.
Björn Pollex
15

Hier ist ein kurzes Beispiel, wie C ++ verwendet wird rdbuf. Ich habe das aus dem Internet bekommen. Ich kann meine ursprüngliche Quelle dazu nicht finden:

#include <fstream>
#include <iostream>

int main () 
{
  std::ifstream f1 ("C:\\me.txt",std::fstream::binary);

  std::ofstream f2 ("C:\\me2.doc",std::fstream::trunc|std::fstream::binary);

  f2<<f1.rdbuf();

  return 0;
}
Thomas Matthews
quelle
8
Die beste, nicht portable Methode besteht darin, das Betriebssystem Ihre Datei kopieren zu lassen. Das ist schließlich ein Teil dessen, was es für seinen Lebensunterhalt tut; Das Rad muss nicht neu erfunden werden .
Thomas Matthews
16
<fstream.h>? <iostream.h>? Keine Namespaces? Was ist es, die neunziger Jahre?
BarbaraKwarc
@BarbaraKwarc: Aktualisiert gemäß Ihrer Anfrage.
Thomas Matthews
14
 sizeof(buffer) == sizeof(char*) 

Verwenden Sie stattdessen die Länge.

Auch besser fopenmit " wb" zu verwenden ....

Alexey Sudachen
quelle
Kann nicht buffer.length()für Puffer verwendet werden, enthält möglicherweise NULL-Werte, wodurch der Zweck von strlen / length () zunichte gemacht wird.
John Greene
Besser zu benutzen sizeof(buffer).
John Greene
7

sizeof (buffer) ist die Größe eines Zeigers in Ihrer letzten Zeile, NICHT die tatsächliche Größe des Puffers. Sie müssen stattdessen die bereits festgelegte "Länge" verwenden

jcoder
quelle
4

Sie sollten Länge anstelle von sizeof (Puffer) an fwrite übergeben.

Retrodrone
quelle
-1

Es gibt einen viel einfacheren Weg. Dies ist egal, ob es sich um eine Binär- oder Textdatei handelt.

Verwenden Sie noskipws.

char buf[SZ];
ifstream f("file");
int i;
for(i=0; f >> noskipws >> buffer[i]; i++);
ofstream f2("writeto");
for(int j=0; j < i; j++) f2 << noskipws << buffer[j];
Zeta
quelle
-2

Dies kann mit einfachen Befehlen im folgenden Snippet erfolgen.

Kopiert die gesamte Datei beliebiger Größe. Keine Größenbeschränkung!

Verwenden Sie einfach diese. Getestet und funktioniert !!

#include<iostream>
#include<fstream>
using namespace std;
int main()
{
  ifstream infile;
  infile.open("source.pdf",ios::binary|ios::in);

  ofstream outfile;
  outfile.open("temppdf.pdf",ios::binary|ios::out);

  int buffer[2];
  while(infile.read((char *)&buffer,sizeof(buffer)))
  {
      outfile.write((char *)&buffer,sizeof(buffer));
  }

  infile.close();
  outfile.close();
  return 0;
}

Eine kleinere Puffergröße wäre hilfreich beim Kopieren kleiner Dateien. Sogar "char buffer [2]" würde den Job machen.

iMajetyHK
quelle
8
Und was ist, wenn die Dateigröße nicht ein Vielfaches der Puffergröße ist? Warum müssen Sie außerdem Ihren Puffer als int[]statt deklarieren char[]?
Firegurafiku
Ich habe bereits erwähnt, dass es auch mit char[]Dateien jeder Größe funktioniert, was bedeutet, dass es keine Bedingung gibt, dass die Dateigröße ein Vielfaches der Puffergröße sein sollte.
iMajetyHK
Die Tatsache, dass Sie sagten, dass es funktioniert, bedeutet nicht, dass es funktioniert. Die Tatsache, dass es nicht funktioniert, bedeutet, dass es nicht funktioniert.
Nunojpg