C++ 如何使用std::fstream以可移植的方式处理二进制文件?

C++ 如何使用std::fstream以可移植的方式处理二进制文件?,c++,C++,std::fstream类的put/get方法对char参数而不是int进行操作。 是否有一种可移植的方式将这些字符字节表示为整数? (我天真的期望是二进制文件是字节序列, i、 e.整数序列) 为了使这个问题更具体,考虑以下两个函数: void print_binary_file_to_cout( const std::string &filename) { std::ifstream ifs(filename, std::ios_base::binary|std::ios_b

std::fstream
类的put/get方法对char参数而不是int进行操作。 是否有一种可移植的方式将这些字符字节表示为整数? (我天真的期望是二进制文件是字节序列, i、 e.整数序列)

为了使这个问题更具体,考虑以下两个函数:

void print_binary_file_to_cout( const std::string &filename)
{
    std::ifstream ifs(filename, std::ios_base::binary|std::ios_base::in);
    char c; 
    while(ifs.get(c))
        std::cout << static_cast<int>(c) << std::endl;
}
void打印二进制文件到cout(const std::string和filename)
{
std::ifstream ifs(文件名,std::ios_base::binary | std::ios_base::in);
字符c;
while(if.get(c))
标准::cout cInt&&cInt!=无字符)
ofs.put(静态铸造(cInt));
}
现在,假设一个函数在Visual Studio的Windows上编译,另一个在Linux的gcc中编译。如果print…()的输出作为make…()的输入 原始文件会被复制吗

我想不会,所以我在问如何正确地实施这个想法,即。
如何在二进制文件中获得可移植(且人类可理解)的字节表示法?

最常见的人类可读字节表示法是十六进制(以16为基数)表示法。通过将
std::hex
传递到流中,可以告诉iostreams使用十六进制格式
std::hex
相应地修改输入和输出流的流行为。这种格式也是规范的,可以独立于编译器和平台工作,并且不需要在值之间使用分隔符(如换行符)。作为停止值,可以使用[0-9a-fA-F]之外的任何字符


请注意,您应该使用无符号字符。

有很多代码,tat假设字符函数可以正确地处理无符号字符变量,可能是静态转换,形式有点相同,但是语言律师会说,如果您编写的是“完美的”可移植代码,就不能依赖这种假设

幸运的是,reinterpret_cast确实提供了将任何指针转换为指向有符号或无符号字符的指针的功能,这是最容易获得的

所有二进制文件的顶部注释:

在windows上,文件必须以二进制模式打开,否则任何代码为13的字节都会神秘地消失


要存储大于256的数字,您需要跨越多个字节值。您需要确定执行此操作的约定:第一个字节是值的最小部分还是最重要部分。某些架构(arm本机和68K)使用“大端”模型,其中最高有效字节位于第一位,而intel(以及处于切换模式的arm)使用“小端”模型。如果要逐字节读取,只需指定它。

我不明白您想做什么?是否要将二进制文件转换为文本?一般来说,是的,像您这样强制转换char和int类型是独立于编译器和平台的,因为所有平台上的int都足够大。最常见的人类可读字节表示法是十六进制(base 16)表示法。例如,在色码中大量使用。但在二进制文件编辑器中也是如此。@ypnos我试图理解如何操作二进制文件。我知道如何处理数字(整数),但我不知道如何处理字符。至于十六进制表示法——仍然存在一个问题,即如何以可移植的方式将字节转换为int(无论整数是写为十六进制还是dec),char已经是整数了。每个字节都是一个整数。范围为0…255或-128…127,具体取决于您如何解释它。字母“a”在ASCII表中有一个与其相关联的数字。@谢谢您的回答。但是,“取决于你如何解释它”这一部分确实让我感到困扰。在你下面的回答中,你还提到我应该使用无符号字符。但是我如何才能做到这一点(以可移植的方式)?我的意思是,get()引用char。put()引用char,但是我可以为char指定255(如果它跨越-128…127),而不会导致未定义的行为吗?
void make_binary_file_from_cin( const std::string &filename)
{ 
    std::ofstream ofs(filename, std::ios_base::binary|std::ios_base::out);
    const int no_char = 256;
    int cInt = no_char; 
    while(std::cin>>cInt && cInt!=no_char )
        ofs.put( static_cast<char>( cInt ) );
}