Đọc và ghi tệp nhị phân


103

Tôi đang cố gắng viết mã để đọc một tệp nhị phân vào bộ đệm, sau đó ghi bộ đệm vào một tệp khác. Tôi có mã sau đây, nhưng bộ đệm chỉ lưu trữ một vài ký tự ASCII từ dòng đầu tiên trong tệp và không có gì khác.

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
Bạn nên quyết định sử dụng xử lý tệp iostream hoặc C. Vui lòng không sử dụng cả hai.
frast

Câu trả lời:


172

Nếu bạn muốn làm điều này theo cách C ++, hãy làm như sau:

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

Nếu bạn cần dữ liệu đó trong bộ đệm để sửa đổi nó hoặc điều gì đó, hãy làm như sau:

#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
Điều gì sẽ xảy ra nếu tôi chỉ muốn sao chép một số đoạn dữ liệu vào bộ đệm. Tôi phải làm việc đó như thế nào? Giả sử 1024 byte.
likern

8
@Mikhail Tại đây bạn có thể tìm thấy một số điểm chuẩn.
Paolo M

3
AFAIK, các tệp nhị phân đôi khi chứa các ký tự không thể đọc được, trên thực tế, chúng hoàn toàn không phải là ký tự. Mã này có an toàn để đọc tệp cơ sở không phải văn bản không? Kiến thức của tôi là ngắn trong phạm vi này :)
Andiana

5
cái gọi charlà được sử dụng trong C / C ++ để lưu trữ các byte (và đã tồn tại trong 40 năm qua). thật an toàn khi làm như vậy, miễn là bạn không cố thực sự SỬ DỤNG dữ liệu đó dưới dạng ký tự (không sử dụng strlen () trên đó, không in nó ra bảng điều khiển, v.v.). c ++ 17 giới thiệu std::bytecho mục đích này (mà vẫn còn char thực sự chartrong ngụy trang)
d.Candela

2
@DavidTran Không thể nói mà không biết thêm - điều này có vẻ như bạn nên tạo một ví dụ tối thiểu mô phỏng lại vấn đề, sau đó đăng câu hỏi.
Björn Pollex

15

Đây là một ví dụ ngắn gọn, cách sử dụng C ++ rdbuf. Tôi lấy cái này từ web. Tôi không thể tìm thấy nguồn gốc của mình về điều này:

#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
Phương pháp tốt nhất, không di động, là để hệ điều hành sao chép tệp của bạn. Rốt cuộc, đó là một phần của những gì nó làm để kiếm sống; không cần phải phát minh lại bánh xe .
Thomas Matthews

16
<fstream.h>? <iostream.h>? Không có không gian tên? Nó là gì, những năm chín mươi?
BarbaraKwarc

@BarbaraKwarc: Đã cập nhật theo yêu cầu của bạn.
Thomas Matthews

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

Sử dụng chiều dài để thay thế.

Ngoài ra, tốt hơn nên sử dụng fopenvới " wb" ....


Không thể sử dụng buffer.length()cho bộ đệm có thể có giá trị NULL bên trong nó, do đó đánh bại mục đích của strlen / length ().
John Greene

Tốt hơn để sử dụng sizeof(buffer).
John Greene

8

sizeof (bộ đệm) là kích thước của một con trỏ trên dòng cuối cùng của bạn KHÔNG phải là kích thước thực của bộ đệm. Thay vào đó, bạn cần sử dụng "độ dài" mà bạn đã thiết lập


4

Bạn nên chuyển chiều dài vào fwrite thay vì sizeof (bộ đệm).


-1

Có một cách đơn giản hơn nhiều. Điều này không quan tâm nếu nó là tệp nhị phân hay tệp văn bản.

Sử dụng 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

Nó có thể được thực hiện bằng các lệnh đơn giản trong đoạn mã sau.

Sao chép toàn bộ tệp có kích thước bất kỳ. Không hạn chế kích thước!

Chỉ cần sử dụng cái này. Đã thử nghiệm và làm việc !!

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

Có kích thước bộ đệm nhỏ hơn sẽ hữu ích trong việc sao chép các tệp nhỏ. Ngay cả "bộ đệm char [2]" sẽ thực hiện công việc.


8
Và điều gì sẽ xảy ra nếu kích thước tệp không phải là nhiều kích thước bộ đệm? Hơn nữa, tại sao bạn phải khai báo bộ đệm của mình int[]thay vì char[]?
firegurafiku

Tôi đã đề cập rằng nó cũng hoạt động với char[]các tệp có kích thước bất kỳ, có nghĩa là không có điều kiện rằng kích thước tệp phải bằng nhiều kích thước bộ đệm.
iMajetyHK

Thực tế là bạn đã nói nó hoạt động không có nghĩa là nó hoạt động. Thực tế là nó không hoạt động có nghĩa là nó không hoạt động.
nunojpg
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.