Читання та запис двійкового файлу


103

Я намагаюся написати код, щоб прочитати двійковий файл у буфер, а потім записати буфер в інший файл. У мене є наступний код, але буфер зберігає лише пару символів 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 для обробки файлів. Не використовуйте обох.
фраст

Відповіді:


172

Якщо ви хочете зробити це способом 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 Тут ви можете знайти порівняльний аналіз.
Паоло М

3
AFAIK, двійкові файли іноді містять нечитабельні символи, насправді вони зовсім не є символами. Чи безпечний цей код для читання нетекстового базового файлу? Мої знання в цьому діапазоні короткі :)
Andiana

5
так званий charвикористовується в C / C ++ для зберігання байтів (і був останні 40 років). це безпечно робити, доки ви не намагаєтесь фактично ВИКОРИСТОВУвати ці дані як символи (не використовуйте strlen () на ньому, не друкуйте їх на консолі тощо). c ++ 17 вводить std::byteдля цієї мети (що досі є char
загадковою

2
@DavidTran Не можу сказати, не знаючи більше - це здається, ви повинні створити мінімальний приклад, який відтворює проблему, а потім опублікувати питання.
Бьорн

15

Ось короткий приклад використання способу 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
Найкращий, не портативний метод - дозволити ОС копіювати ваш файл. Зрештою, це частина того, що вона робить для життя; не потрібно винаходити колесо .
Томас Меттьюз

16
<fstream.h>? <iostream.h>? Немає просторів імен? Що це, дев'яностих?
BarbaraKwarc

@BarbaraKwarc: Оновлено відповідно до вашого запиту.
Томас Меттьюз

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

Використовуйте замість довжини.

Також краще використовувати fopen" wb" ....


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

Краще використовувати sizeof(buffer).
Джон Грін

8

sizeof (буфер) - це розмір вказівника в останньому рядку НЕ фактичний розмір буфера. Вам потрібно використовувати «довжину», яку ви вже встановили замість цього



-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 [2]" зробив би цю роботу.


8
А що, якщо розмір файлу не кращий розміру буфера? Крім того, чому ви повинні оголошувати буфер як int[]замість char[]?
firegurafiku

Я вже згадував, що він працює char[]і з файлами будь-якого розміру, що означає, що немає жодної умови, щоб розмір файлу був кратним розміру буфера.
iMajetyHK

Те, що ви сказали, що це працює, не означає, що воно працює. Те, що він не працює, означає, що це не працює.
nunojpg
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.