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

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 );
nf313743
источник
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) - это размер указателя на вашей последней строке, а НЕ фактический размер буфера. Вместо этого вам нужно использовать "длину", которую вы уже установили.

jcoder
источник
4

Вы должны передать длину в fwrite вместо 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]" подойдет.

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