Lettura e scrittura di file binari


103

Sto cercando di scrivere il codice per leggere un file binario in un buffer, quindi scrivere il buffer in un altro file. Ho il seguente codice, ma il buffer memorizza solo un paio di caratteri ASCII dalla prima riga del file e nient'altro.

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 );

28
Dovresti decidere di utilizzare iostream o la gestione dei file C. Si prega di non utilizzare entrambi.
dal

Risposte:


172

Se vuoi farlo in C ++, fallo in questo modo:

#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));
}

Se hai bisogno di quei dati in un buffer per modificarli o qualcosa del genere, fai questo:

#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), {});

}

4
E se volessi copiare solo un segmento di dati nel buffer. Come posso farlo? Diciamo 1024 byte.
come il

8
@Mikhail Qui puoi trovare alcuni benchmark.
Paolo M

3
AFAIK, i file binari a volte contengono caratteri illeggibili, infatti non lo sono affatto. Questo codice è sicuro per la lettura di file di base non di testo? La mia conoscenza è breve in questo intervallo :)
Andiana

5
cosiddetto charè usato in C / C ++ per memorizzare i byte (e lo è stato negli ultimi 40 anni). è sicuro farlo, a patto di non provare a USARE effettivamente quei dati come caratteri (non usare strlen () su di esso, non stamparlo sulla console, ecc.). c ++ 17 introduce std::byteper questo scopo (che è ancora char in realtà charsotto mentite spoglie)
d.Candela

2
@DavidTran Non posso dire senza saperne di più: sembra che dovresti creare un esempio minimo che riproduca il problema e quindi pubblicare una domanda.
Björn Pollex

16

Ecco un breve esempio, il modo in cui C ++ usa rdbuf. L'ho preso dal web. Non riesco a trovare la mia fonte originale su questo:

#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;
}

8
Il metodo migliore, non portabile, è lasciare che il sistema operativo copi il tuo file. Dopotutto, questo fa parte di ciò che fa per vivere; non c'è bisogno di reinventare la ruota .
Thomas Matthews

@BarbaraKwarc: aggiornato in base alla tua richiesta.
Thomas Matthews

14
 sizeof(buffer) == sizeof(char*) 

Usa invece la lunghezza.

Inoltre, meglio usare fopencon " wb" ....


Non può essere utilizzato buffer.length()per buffer potrebbe avere valori NULL al suo interno, vanificando così lo scopo di strlen / length ().
John Greene

Meglio usare sizeof(buffer).
John Greene

8

sizeof (buffer) è la dimensione di un puntatore sull'ultima riga NON la dimensione effettiva del buffer. È necessario utilizzare invece la "lunghezza" che hai già stabilito



-1

C'è un modo molto più semplice. A questo non importa se è un file binario o di testo.

Usa 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];

-2

Può essere fatto con semplici comandi nel seguente frammento.

Copia l'intero file di qualsiasi dimensione. Nessun vincolo di dimensione!

Usa questo. Testato e funzionante !!

#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;
}

Avere una dimensione del buffer inferiore sarebbe utile per copiare file piccoli. Anche "char buffer [2]" farebbe il lavoro.


8
E se la dimensione del file non fosse multipla della dimensione del buffer? Inoltre, perché devi dichiarare il tuo buffer come int[]invece di char[]?
firegurafiku

Ho già detto che funziona char[]anche con file di qualsiasi dimensione, il che significa che non c'è condizione che la dimensione del file debba essere un multiplo della dimensione del buffer.
iMajetyHK

Il fatto che tu abbia detto che funziona non significa che funzioni. Il fatto che non funzioni significa che non funziona.
nunojpg
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.