Membaca dan menulis file biner

103

Saya mencoba menulis kode untuk membaca file biner menjadi buffer, lalu menulis buffer ke file lain. Saya memiliki kode berikut, tetapi buffer hanya menyimpan beberapa karakter ASCII dari baris pertama dalam file dan tidak ada yang lain.

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
sumber
28
Anda harus memutuskan untuk menggunakan iostream atau penanganan file C. Harap jangan gunakan keduanya.
frast

Jawaban:

172

Jika Anda ingin melakukan ini dengan cara C ++, lakukan seperti ini:

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

Jika Anda membutuhkan data itu dalam buffer untuk mengubahnya atau sesuatu, lakukan ini:

#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
sumber
4
Bagaimana jika saya ingin menyalin hanya beberapa segmen data ke buffer. Bagaimana saya bisa melakukannya? Katakanlah 1024 byte.
Seperti
8
@Mikhail Di sini Anda dapat menemukan beberapa benchmarking.
Paolo M
3
AFAIK, file biner terkadang mengandung char yang tidak terbaca, pada kenyataannya, mereka sama sekali bukan char. Apakah kode ini aman untuk membaca file berbasis non-teks? Pengetahuan saya pendek dalam kisaran ini :)
Andiana
5
apa yang disebut chardigunakan dalam C / C ++ untuk menyimpan byte (dan telah digunakan selama 40 tahun terakhir). aman untuk melakukannya, selama Anda tidak mencoba untuk benar-benar MENGGUNAKAN data itu sebagai karakter (jangan gunakan strlen () di atasnya, jangan cetak ke konsol, dll). c ++ 17 memperkenalkan std::byteuntuk tujuan ini (yang sebenarnya masih chardisamarkan)
d. Candela
2
@DavidTran Tidak dapat mengatakan tanpa mengetahui lebih lanjut - ini sepertinya Anda harus membuat contoh minimal yang mereproduksi masalah, lalu memposting pertanyaan.
Björn Pollex
16

Berikut adalah contoh singkat, cara C ++ menggunakan rdbuf. Saya mendapatkan ini dari web. Saya tidak dapat menemukan sumber asli saya tentang ini:

#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
sumber
8
Metode terbaik dan non-portabel adalah membiarkan OS menyalin file Anda. Bagaimanapun, itu adalah bagian dari apa yang dilakukannya untuk mencari nafkah; tidak perlu menemukan kembali roda .
Thomas Matthews
@BarbaraKwarc: Diperbarui sesuai permintaan Anda.
Thomas Matthews
14
 sizeof(buffer) == sizeof(char*) 

Gunakan panjang sebagai gantinya.

Selain itu, lebih baik digunakan fopendengan " wb" ....

Alexey Sudachen
sumber
Tidak dapat digunakan buffer.length()untuk buffer mungkin memiliki nilai NULL di dalamnya sehingga mengalahkan tujuan strlen / length ().
John Greene
Lebih baik digunakan sizeof(buffer).
John Greene
8

sizeof (buffer) adalah ukuran pointer pada baris terakhir Anda BUKAN ukuran buffer sebenarnya. Anda perlu menggunakan "panjang" yang sudah Anda tetapkan

jcoder.dll
sumber
4

Anda harus meneruskan panjang ke fwrite daripada sizeof (buffer).

retrodrone
sumber
-1

Ada cara yang lebih sederhana. Ini tidak peduli apakah itu file biner atau teks.

Gunakan 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
sumber
-2

Itu dapat dilakukan dengan perintah sederhana di cuplikan berikut.

Menyalin seluruh file dengan ukuran berapa pun. Tidak ada batasan ukuran!

Gunakan saja ini. Diuji Dan Bekerja !!

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

Memiliki ukuran buffer yang lebih kecil akan membantu dalam menyalin file-file kecil. Bahkan "char buffer [2]" akan melakukan pekerjaan itu.

iMajetyHK
sumber
8
Dan bagaimana jika ukuran file tidak berlipat ganda dari ukuran buffer? Selain itu, mengapa Anda harus mendeklarasikan buffer Anda sebagai int[]pengganti char[]?
firegurafiku
Saya sudah menyebutkan itu bekerja dengan char[]juga dan file dengan ukuran berapa pun yang berarti tidak ada syarat bahwa ukuran file harus kelipatan ukuran buffer.
iMajetyHK
Fakta bahwa Anda mengatakan itu berhasil tidak berarti itu berhasil. Fakta bahwa itu tidak berhasil berarti tidak berhasil.
nunojpg