以二进制格式写文件

Write file in binary format

本文关键字:文件 格式 二进制      更新时间:2023-10-16

我正在尝试以二进制格式编写文件。我有以下代码,但它将文件保存在文本格式中。

#include <iostream>
#include <fstream>
using namespace std;
int main(){
    std::string ref = "Ecoli. 123";
    unsigned int size = 124;
    std::ofstream supp_info_output("binary_file",  std::ios::out | std::ios::binary); // saving file
    supp_info_output << ref << std::endl;
    supp_info_output << size << std::endl;
    supp_info_output.close();
    std::ifstream supp_info_input("binary_file", std::ios::in | std::ios::binary); // loading file
    std::string supp_info_line;
    while( std::getline( supp_info_input, supp_info_line ).good() ){
        std::cout << supp_info_line << std::endl;
    }
    supp_info_input.close();
}

在代码中,我正在编写一些数据,然后再次读取数据。阅读和写作没有问题,但是我需要二进制格式的文件。

使用::写入二进制数据和ifstream ::阅读以阅读它们。请注意,您应该节省字符串的长度,因为您应该知道要进一步读取多少个字节。

std::string ref = "Ecoli. 123";
unsigned int size = 124;
std::ofstream supp_info_output("binary_file",  std::ios::out | std::ios::binary); // saving file
unsigned int stringLength = ref.length();
supp_info_output.write( (char*)( &stringLength ), sizeof( stringLength ) );
supp_info_output.write( ref.c_str(), ref.length() );
supp_info_output.write( (char*)( &size ), sizeof( size ) );
supp_info_output.close();

这是阅读的方法:

std::string ref;
unsigned int size;
std::ifstream supp_info_input("binary_file", std::ios::in | std::ios::binary); // loading file
unsigned int stringLength;
supp_info_input.read( (char*)( &stringLength ), sizeof( stringLength ) );
ref.resize( stringLength );
supp_info_input.read( (char*)ref.c_str(), stringLength );
supp_info_input.read( (char*)( &size ), sizeof( size ) );
supp_info_input.close();

,如等待中的答案所述,我不喜欢为每个输出语句编写很多代码。取而代之的是,我更喜欢将移位操作员过载,以使用户代码容易且较小的错误容易容易出现。

作为开始点,给出了以下示例。并非所有可能的过载都可能出现,而二进制文件类也少于"准备生产"。它仅作为启动自己的调查的可编译起点。

请记住:二进制文件不是便携式的,二进制表示形式可以从编译器/libc/其他版本的版本更改。它还取决于系统的OS和Endianess,以及架构(32 vs 64位(和许多其他体系。

因此,除非您编写具有定义/out格式定义的处理程序方法,否则通常不应使用二进制数据来使数据持续使用。我的示例简单地写入非常愚蠢的数据存储的记忆,并提到了所有问题。随时为可交换二进制格式启动自己的"完美"实现。

但是,有人应该使用准备好使用无处不在的实现。搜索"序列化器",您会发现像Boost Serialize和其他许多其他LIB一样。

#include <fstream>
#include <cstring>
class BinaryOut: public std::ofstream
{ 
    public:
        BinaryOut( const char* fname ):
           std::ofstream( fname, std::ios::binary )
    {}
};
// use a generic func to use for everything which not handled in special way
template < typename DataType >
BinaryOut& operator << ( BinaryOut& out, const DataType& data )
{
    out.write( (char*)&data, sizeof( DataType ));
    return out;
}
// if pointer type, write not pointer but values which pointer points to:
template < typename DataType >
BinaryOut& operator << ( BinaryOut& out, const DataType*& data )
{
    out.write( (char*)data, sizeof( DataType ));
    return out;
}
// special case for char ptr ( old style c string ) which ends with ''
// use old style c here ( no std::string is involved )
BinaryOut& operator << ( BinaryOut& out, const char* ptr )
{
    out.write( ptr, strlen( ptr ));
    return out; 
}
// may be some more overloads for << if needed...
int main()
{
    BinaryOut out("example.bin");
    int i=123;
    double d=9.876;
    double* ptrd=&d;
    const char* dummy = "Ptr to Text";
    out << i << d  << ptrd << "Hallo, this is a test" << dummy;
}

它比以二进制编写数据要困难得多。我建议使用C文件 *接口,因为许多C 程序员过载&lt;&lt;>>以文本模式插入和提取更高级别的对象。当您去二进制时,您会失去那个。

要插入一个整数,您需要知道它是16位还是32位,大端或小居民。然后,您使用换档,掩码和呼叫fputc((直接编写字节。要插入ASCIIZ字符串,请类似地致电fputc并确保您编写nul。

@klaus是正确的,如果将int传递给&lt;&lt;在二进制文件中,它只需写入文本即可。如果您想编写二进制文件以用&lt;&lt;进行归档,则应将字节流传递到&lt;&lt;。例如,在您的代码中,您需要每次使用&lt;&lt;然后将二进制INT写入您的文件中。您可以检查以下代码:

#include "stdafx.h"
#include <iostream>
#include <fstream>
using namespace std;
union data {
    int i;
    char bytes[4];
};
int main(){
    data src;
    src.i = 0xabcddcba;
    std::ofstream supp_info_output("binary_file", ios::out | ios::binary); // saving file
    supp_info_output << src.bytes[0];
    supp_info_output << src.bytes[1];
    supp_info_output << src.bytes[2];
    supp_info_output << src.bytes[3];
    supp_info_output.close();
    data dst;
    dst.i = 0;
    std::ifstream supp_info_input("binary_file", ios::in | ios::binary); // loading file
    supp_info_input >> dst.bytes[0];
    supp_info_input >> dst.bytes[1];
    supp_info_input >> dst.bytes[2];
    supp_info_input >> dst.bytes[3];
    supp_info_input.close();
    std::cout << ((src.i == dst.i)?"Pass check.":"Failed check.") << std::endl;
    getchar();
}

我认为&lt;&lt;在二进制文件模式下,在二进制文件模式下,无论其类型如何,都应将所有内容视为字节流,例如int,double,short int,...等。