Czytanie i zapisywanie pliku binarnego

103

Próbuję napisać kod, aby odczytać plik binarny w buforze, a następnie zapisać bufor do innego pliku. Mam następujący kod, ale bufor przechowuje tylko kilka znaków ASCII z pierwszej linii w pliku i nic więcej.

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
źródło
28
Powinieneś zdecydować się na obsługę plików iostream lub C. Nie używaj obu.
frast

Odpowiedzi:

172

Jeśli chcesz to zrobić w C ++, zrób to tak:

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

Jeśli potrzebujesz tych danych w buforze, aby je zmodyfikować, zrób to:

#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
źródło
4
A jeśli chcę skopiować tylko część danych do bufora. Jak mogę to zrobić? Powiedzmy, że 1024 bajty.
podobnie jak
8
@Mikhail Tutaj możesz znaleźć testy porównawcze.
Paolo M
3
AFAIK, pliki binarne czasami zawierają nieczytelne znaki, w rzeczywistości wcale nie są znakami. Czy ten kod jest bezpieczny do odczytu nietekstowego pliku podstawowego? Moja wiedza jest krótka w tym zakresie :)
Andiana
5
tak zwany charjest używany w C / C ++ do przechowywania bajtów (i jest od 40 lat). jest to bezpieczne, o ile nie próbujesz faktycznie UŻYWAĆ tych danych jako znaków (nie używaj na nich strlen (), nie drukuj na konsoli itp.). c ++ 17 wprowadza std::bytedo tego celu (która jest nadal char faktycznie charw przebraniu)
d.Candela
2
@DavidTran Nie mogę powiedzieć, nie wiedząc więcej - wydaje się, że powinieneś stworzyć minimalny przykład, który odtwarza problem, a następnie zadać pytanie.
Björn Pollex
16

Oto krótki przykład, sposób użycia w C ++ rdbuf. Mam to z sieci. Nie mogę znaleźć mojego oryginalnego źródła na ten temat:

#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
źródło
8
Najlepszą, nieprzenośną metodą jest umożliwienie systemowi operacyjnemu skopiowania pliku. W końcu jest to część tego, czym się zajmuje; nie ma potrzeby odkrywania na nowo koła .
Thomas Matthews,
@BarbaraKwarc: Zaktualizowano na Twoje żądanie.
Thomas Matthews
14
 sizeof(buffer) == sizeof(char*) 

Zamiast tego użyj długości.

Lepiej też używać fopenz „ wb” ....

Alexey Sudachen
źródło
Nie można użyć buffer.length()dla bufora, może mieć w sobie wartości NULL, co jest sprzeczne z celem strlen / length ().
John Greene,
Lepiej używać sizeof(buffer).
John Greene
8

sizeof (buffer) to rozmiar wskaźnika w ostatniej linii, a NIE rzeczywisty rozmiar bufora. Zamiast tego musisz użyć już ustalonej długości

jcoder
źródło
4

Długość należy przekazać do fwrite zamiast sizeof (buffer).

retrodrone
źródło
-1

Jest o wiele prostszy sposób. Nie ma znaczenia, czy jest to plik binarny czy tekstowy.

Użyj 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
źródło
-2

Można to zrobić za pomocą prostych poleceń w poniższym fragmencie.

Kopiuje cały plik o dowolnym rozmiarze. Brak ograniczeń rozmiaru!

Po prostu użyj tego. Przetestowane i działa !!

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

Mniejszy rozmiar bufora byłby pomocny w kopiowaniu małych plików. Nawet "char buffer [2]" załatwiłby sprawę.

iMajetyHK
źródło
8
A co, jeśli rozmiar pliku nie jest wielokrotnością rozmiaru bufora? Co więcej, dlaczego musisz zadeklarować swój bufor jako int[]zamiast char[]?
firegurafiku
Wspomniałem już, że działa char[]również z plikami o dowolnym rozmiarze, co oznacza, że ​​nie ma warunku, aby rozmiar pliku był wielokrotnością rozmiaru bufora.
iMajetyHK
To, że powiedziałeś, że działa, nie oznacza, że ​​działa. Fakt, że nie działa, oznacza, że ​​nie działa.
nunojpg