Чтение и запись двоичного файла


104

Я пытаюсь написать код, чтобы прочитать двоичный файл в буфер, а затем записать буфер в другой файл. У меня есть следующий код, но в буфере хранится только пара символов ASCII из первой строки файла и ничего больше.

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
Вы должны решить использовать iostream или обработку файлов C. Пожалуйста, не используйте оба.
— Frast

Ответы:


174

Если вы хотите сделать это способом C ++, сделайте это так:

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

Если вам нужны эти данные в буфере, чтобы изменить их или что-то в этом роде, сделайте следующее:

#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
Что, если я хочу скопировать в буфер только некоторый сегмент данных. Как я могу это сделать? Скажем, 1024 байта.
— Likern

8
@Mikhail Здесь вы можете найти сравнительный анализ.
— Paolo M

3
AFAIK, двоичные файлы иногда содержат нечитаемый char, на самом деле они вообще не char. Безопасен ли этот код для чтения нетекстового базового файла? Мои знания в этом диапазоне
— ограничены

5
так называемый charиспользуется в C / C ++ для хранения байтов (и использовался в течение последних 40 лет). это безопасно, если вы не пытаетесь фактически ИСПОЛЬЗОВАТЬ эти данные как символы (не используйте на них strlen (), не выводите их на консоль и т. д.). c ++ 17 вводит std::byteдля этой цели (который до сих пор остается charзамаскированным
— символом

2
@DavidTran Не могу сказать, не зная больше - похоже, вы должны создать минимальный пример, воспроизводящий проблему, а затем опубликовать вопрос.
— Björn Pollex

16

Вот краткий пример использования C ++ rdbuf. Я получил это из Интернета. Я не могу найти свой первоисточник по этому поводу:

#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
Лучший, непереносимый метод - позволить ОС скопировать ваш файл. В конце концов, это часть того, чем он зарабатывает на жизнь; не нужно изобретать велосипед .
— Thomas Matthews

@BarbaraKwarc: Обновлено по вашему запросу.
— Thomas Matthews

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

Вместо этого используйте длину.

Также лучше использовать fopenс " wb" ....


Невозможно использовать buffer.length()для буфера, внутри него могут быть значения NULL, что противоречит цели strlen / length ().
— Джон Грин

Лучше использовать sizeof(buffer).
— Джон Грин

8

sizeof (buffer) - это размер указателя на вашей последней строке, а НЕ фактический размер буфера. Вместо этого вам нужно использовать "длину", которую вы уже установили.



-1

Есть более простой способ. Неважно, двоичный это файл или текстовый.

Используйте 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

Это можно сделать с помощью простых команд в следующем фрагменте.

Копирует весь файл любого размера. Никаких ограничений по размеру!

Просто используйте это. Протестировано и работает !!

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

При копировании крошечных файлов было бы полезно иметь меньший размер буфера. Даже "char buffer [2]" подойдет.


8
А что, если размер файла не кратен размеру буфера? Более того, почему вы должны объявлять свой буфер как int[]вместо char[]?
— firegurafiku

Я уже упоминал, что он также работает и с char[]файлами любого размера, что означает, что нет условия, что размер файла должен быть кратным размеру буфера.
— iMajetyHK

Тот факт, что вы сказали, что это работает, не означает, что это работает. Тот факт, что он не работает, означает, что он не работает.
— nunojpg
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.