İkili dosyayı okuma ve yazma


108

Bir ikili dosyayı bir arabelleğe okumak için kod yazmaya, ardından arabelleği başka bir dosyaya yazmaya çalışıyorum. Aşağıdaki koda sahibim, ancak arabellekte yalnızca dosyanın ilk satırından birkaç ASCII karakteri depolanır ve başka hiçbir şey saklanmaz.

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
İostream veya C dosya işlemeyi kullanmaya karar vermelisiniz. Lütfen ikisini birden kullanmayın.
frast

Yanıtlar:


176

Bunu C ++ yolu ile yapmak istiyorsanız, şu şekilde yapın:

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

Bu veriyi değiştirmek için arabellekte ihtiyacınız varsa, şunu yapın:

#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
Sadece bazı veri segmentlerini arabelleğe kopyalamak istersem ne olur? Nasıl yapabilirim? 1024 bayt diyelim.
2014

8
@Mikhail Burada bazı karşılaştırmalar bulabilirsiniz.
Paolo M

3
AFAIK, ikili dosyalar bazen okunamayan karakterler içerirler, aslında onlar karakter değildirler. Bu kod, metin olmayan temel dosyayı okumak için güvenli midir?
Bilgim

5
sözde charC / C ++ 'da baytları depolamak için kullanılır (ve son 40 yıldır kullanılmaktadır). Bu veriyi karakter olarak KULLANMAYINIZ (üzerinde strlen () kullanmayın, konsola yazdırmayın, vb.) bunu yapmak güvenlidir . c ++ 17 std::bytebu amaç için tanıtıyor (ki bu hala charkılık değiştirmiş durumda)
d.Candela

2
@DavidTran Daha fazlasını bilmeden söyleyemem - bu, sorunu yeniden üreten minimal bir örnek oluşturmalı ve ardından bir soru göndermelisiniz.
Björn Pollex

16

İşte kısa bir örnek rdbuf,. Bunu internetten aldım. Orijinal kaynağımı bu konuda bulamıyorum:

#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
En iyi, taşınabilir olmayan yöntem, işletim sisteminin dosyanızı kopyalamasına izin vermektir. Sonuçta, yaşamak için yaptıklarının bir parçası bu; tekerleği yeniden icat etmeye gerek yok .
Thomas Matthews

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

Bunun yerine uzunluğu kullanın.

Ayrıca, fopen" wb" ile kullanmak daha iyidir ...


Kullanılamaz buffer.length()böylece strlen / uzunlukta amacı yenerek içindeki NULL değerlerine sahip olabilir tampon için ().
John Greene

Kullanması daha iyi sizeof(buffer).
John Greene

8

sizeof (arabellek), arabelleğin gerçek boyutu DEĞİL, son satırınızdaki bir işaretçinin boyutudur. Bunun yerine önceden belirlediğiniz "uzunluğu" kullanmanız gerekir



-2

Çok daha basit bir yolu var. İkili veya metin dosyası olması umurunda değil.

Noskipws kullanın.

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

Daha anlaşılır hale getirmek için bu konuyu ayrıntılarıyla
anlatmak isteyebilirsiniz

-2

Aşağıdaki kod parçacığında basit komutlarla yapılabilir.

Herhangi bir boyuttaki tüm dosyayı kopyalar. Boyut kısıtlaması yok!

Sadece bunu kullan. Test Edildi ve Çalışıyor !!

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

Daha küçük bir arabellek boyutuna sahip olmak, küçük dosyaların kopyalanmasında yardımcı olacaktır. Hatta "karakter tamponu [2]" bile iş görür.


8
Peki ya dosya boyutu arabellek boyutunun katı değilse? Dahası, neden arabelleğinizi int[]yerine olarak bildirmeniz gerekiyor char[]?
firegurafiku

Daha önce de çalıştığından char[]ve herhangi bir boyuttaki dosyayla çalıştığından bahsetmiştim, bu da dosya boyutunun birden fazla arabellek boyutu olması gerektiği anlamına gelmez.
iMajetyHK

Çalıştığını söylemen işe yaradığı anlamına gelmez. Çalışmadığı gerçeği, çalışmadığı anlamına gelir.
nunojpg
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.