Lecture et écriture d'un fichier binaire

104

J'essaie d'écrire du code pour lire un fichier binaire dans un tampon, puis d'écrire le tampon dans un autre fichier. J'ai le code suivant, mais le tampon ne stocke que quelques caractères ASCII de la première ligne du fichier et rien d'autre.

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
la source
28
Vous devez décider d'utiliser la gestion des fichiers iostream ou C. Veuillez ne pas utiliser les deux.
vendredi

Réponses:

174

Si vous voulez faire cela à la manière C ++, procédez comme suit:

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

Si vous avez besoin de ces données dans un tampon pour les modifier ou quelque chose, procédez comme suit:

#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
la source
4
Que faire si je veux copier uniquement un segment de données dans la mémoire tampon. Comment je peux le faire? Disons 1024 octets.
likern
8
@Mikhail Ici vous pouvez trouver quelques benchmarking.
Paolo M
3
AFAIK, les fichiers binaires contiennent parfois des caractères illisibles, en fait, ils ne sont pas du tout des caractères. Ce code est-il sûr pour lire un fichier de base non textuel? Mes connaissances sont courtes dans cette gamme :)
Andiana
5
soi-disant charest utilisé en C / C ++ pour stocker des octets (et ce depuis 40 ans). il est sûr de le faire, aussi longtemps que vous ne cherchez pas à réellement USE que les données sous forme de caractères (ne pas utiliser strlen () sur elle, ne pas imprimer à la console, etc.). c ++ 17 introduit std::byteà cet effet (qui est encore du caractère en fait chardéguisé)
d.Candela
2
@DavidTran Je ne peux pas dire sans en savoir plus - cela semble que vous devriez créer un exemple minimal qui reproduit le problème, puis publier une question.
Björn Pollex
16

Voici un court exemple, la manière C ++ utilisant rdbuf. J'ai obtenu ceci sur le Web. Je ne trouve pas ma source originale à ce sujet:

#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
la source
8
La meilleure méthode, non portable, consiste à laisser le système d'exploitation copier votre fichier. Après tout, cela fait partie de ce qu'il fait pour gagner sa vie; pas besoin de réinventer la roue .
Thomas Matthews
@BarbaraKwarc: mis à jour selon votre demande.
Thomas Matthews
14
 sizeof(buffer) == sizeof(char*) 

Utilisez plutôt la longueur.

Aussi, mieux utiliser fopenavec " wb" ....

Alexey Sudachen
la source
Can't use buffer.length()for buffer peut avoir des valeurs NULL à l'intérieur, ce qui va à l'encontre de l'objectif de strlen / length ().
John Greene
Mieux vaut utiliser sizeof(buffer).
John Greene
8

sizeof (buffer) est la taille d'un pointeur sur votre dernière ligne PAS la taille réelle du buffer. Vous devez utiliser la "longueur" que vous avez déjà établie à la place

jcoder
la source
4

Vous devez passer length dans fwrite au lieu de sizeof (buffer).

rétrodrone
la source
-1

Il existe un moyen beaucoup plus simple. Cela ne se soucie pas s'il s'agit d'un fichier binaire ou texte.

Utilisez 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
la source
-2

Cela peut être fait avec des commandes simples dans l'extrait de code suivant.

Copie le fichier entier de n'importe quelle taille. Aucune contrainte de taille!

Utilisez simplement ceci. Testé et fonctionnel !!

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

Avoir une taille de tampon plus petite serait utile pour copier de petits fichiers. Même "char buffer [2]" ferait l'affaire.

iMajetyHK
la source
8
Et si la taille du fichier n'est pas multiple de la taille du tampon? De plus, pourquoi devez-vous déclarer votre tampon comme int[]au lieu de char[]?
firegurafiku
J'ai déjà mentionné que cela fonctionne char[]également avec les fichiers de toute taille, ce qui signifie qu'il n'y a aucune condition selon laquelle la taille du fichier doit être un multiple de la taille du tampon.
iMajetyHK
Le fait que vous ayez dit que cela fonctionne ne signifie pas que cela fonctionne. Le fait que cela ne fonctionne pas signifie que cela ne fonctionne pas.
nunojpg