读写二进制文件

Posted

技术标签:

【中文标题】读写二进制文件【英文标题】:Reading and writing binary file 【发布时间】:2011-07-22 04:13:45 【问题描述】:

我正在尝试编写代码以将二进制文件读入缓冲区,然后将缓冲区写入另一个文件。我有以下代码,但缓冲区仅存储文件第一行中的几个 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 );

【问题讨论】:

您应该决定使用 iostream 或 C 文件处理。请不要同时使用。 【参考方案1】:

sizeof(buffer) 是最后一行指针的大小,而不是缓冲区的实际大小。 您需要改用已经建立的“长度”

【讨论】:

【参考方案2】:

您应该将长度传递给 fwrite 而不是 sizeof(buffer)。

【讨论】:

【参考方案3】:
 sizeof(buffer) == sizeof(char*) 

改用长度。

另外,最好将fopen 与“wb”一起使用....

【讨论】:

Can't use buffer.length() for buffer 里面可能有 NULL 值,从而违背了 strlen/length() 的目的。 最好使用sizeof(buffer)【参考方案4】:

如果您想以 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), );


【讨论】:

如果我只想复制一部分数据到缓冲区怎么办。我该怎么做?假设 1024 字节。 @Mikhail Here 你可以找到一些基准测试。 AFAIK,二进制文件有时包含不可读的字符,事实上,它们根本不是字符。此代码对于读取非文本基本文件是否安全?我的知识在这个范围内很短:) 所谓的char 在 C/C++ 中用于存储字节(过去 40 年一直如此)。这样做是安全的,只要您不尝试将数据实际 USE 作为字符(不要在其上使用 strlen(),不要将其打印到控制台等)。 c++17为此引入了std::byte(实际上还是char变相的char @DavidTran 不能说不知道更多 - 这似乎你应该创建一个重现问题的最小示例,然后发布问题。【参考方案5】:

这是一个简短的示例,使用rdbuf 的C++ 方式。我从网上得到这个。我找不到我的原始来源:

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

【讨论】:

最好的、不可移植的方法是让操作系统复制你的文件。毕竟,这是它谋生的一部分。无需重新发明***【参考方案6】:

可以通过下面sn-p中的简单命令来完成。

复制任意大小的整个文件。没有大小限制!

就用这个吧。测试和工作!

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

具有较小的缓冲区大小将有助于复制小文件。甚至“字符缓冲区[2]” 会做这项工作。

【讨论】:

如果文件大小不是缓冲区大小的倍数怎么办?此外,为什么必须将缓冲区声明为int[] 而不是char[] 我已经提到它也适用于char[] 和任何大小的文件,这意味着文件大小不应该是缓冲区大小的倍数。 你说它有效并不意味着它有效。它不起作用的事实意味着它不起作用。 您至少可以将 'int buffer[2]' 更改为 'char buffer[1]' 以在不更改代码修复错误的情况下正常工作。【参考方案7】:

有一个更简单的方法。这不关心它是二进制文件还是文本文件。

使用 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];

或者你可以只使用字符串而不是缓冲区。

string s; char c;
ifstream f("image.jpg");
while(f >> noskipws >> c) s += c;
ofstream f2("copy.jpg");
f2 << s;

通常流会跳过空格字符,例如空格或换行符、制表符和所有其他控制字符。 但是 noskipws 使所有字符都被转移。 所以这不仅会复制文本文件,还会复制二进制文件。 而且stream内部使用buffer,估计速度不会慢。

【讨论】:

您可能需要详细说明以使其更易于理解【参考方案8】:

这是标准 C++ 14 的实现,使用 vectorstuples 来读写Text,Binary and Hex files

片段代码:

try 
if (file_type == BINARY_FILE) 

    /*Open the stream in binary mode.*/
    std::ifstream bin_file(file_name, std::ios::binary);

    if (bin_file.good()) 
        /*Read Binary data using streambuffer iterators.*/
        std::vector<uint8_t> v_buf((std::istreambuf_iterator<char>(bin_file)), (std::istreambuf_iterator<char>()));
        vec_buf = v_buf;
        bin_file.close();
    

    else 
        throw std::exception();
    



else if (file_type == ASCII_FILE) 

    /*Open the stream in default mode.*/
    std::ifstream ascii_file(file_name);
    string ascii_data;

    if (ascii_file.good()) 
        /*Read ASCII data using getline*/
        while (getline(ascii_file, ascii_data))
            str_buf += ascii_data + "\n";

        ascii_file.close();
    
    else 
        throw std::exception();
    


else if (file_type == HEX_FILE) 

    /*Open the stream in default mode.*/
    std::ifstream hex_file(file_name);

    if (hex_file.good()) 
        /*Read Hex data using streambuffer iterators.*/
        std::vector<char> h_buf((std::istreambuf_iterator<char>(hex_file)), (std::istreambuf_iterator<char>()));
        string hex_str_buf(h_buf.begin(), h_buf.end());
        hex_buf = hex_str_buf;

        hex_file.close();
    
    else 
        throw std::exception();
    

完整的源代码可以找到here

【讨论】:

以上是关于读写二进制文件的主要内容,如果未能解决你的问题,请参考以下文章

C#读写二进制文件

VB.NET 怎么读写二进制文件,类似Open

C++ 二进制文件 & 顺序读写

请问VB如何读写二进制文件

二进制文件的读写

二进制文件的读写