将十六进制写入文件

6

我有一个读取文件的程序,它会读取文件的十六进制并进行修改,最后将修改后的十六进制存储在一个std::string中。

例如,我如何将这个字符串写入文件?

std::string wut="b6306edf953a6ac8d17d70bda3e93f2a3816eac333d1ac78";

和获取其值
.0n..:j..}p...?*8...3..x

在输出的文件中?

我更愿意不使用 sprintf,但如果必要的话,我会尽力而为。


1
你说的"文件的十六进制"是什么意思?你是在考虑文件的二进制、未格式化的内容,还是单个十六进制值? - Paweł Stawarz
所有内容都转换为十六进制。我对这个领域的知识很新,所以... - Moon
1
如果我理解正确的话,您正在读取一个二进制文件,将数据存储为十六进制字符串,然后想要将修改后的数据写回到文件中(以二进制形式)? - Zac Howland
定义二进制文件。说实话,它不是特定格式的文件;所以从某种意义上说是的。 - Moon
1
二进制文件意味着“不是文本文件”。所有文件都是二进制的,但文本文件意味着内容应被解释为可打印的文本数据。 - Eugene S
显示剩余3条评论
2个回答

5

如果我正确理解你的问题,你想将文本转换为它的数字等价形式,然后写入文件。根据你在问题中提供的提示,似乎应该逐字节地完成这个操作。下面是一种实现方法。请注意,需要将每个字节从字符串转换为整数值。

#include <string>
#include <sstream>
#include <iostream>
#include <fstream>
#include <ios>

std::string wut = "b6306edf953a6ac8d17d70bda3e93f2a3816eac333d1ac78";

int main()
{
    std::ofstream datafile("c:\\temp\\temp1.dat", std::ios_base::binary | std::ios_base::out);

    char buf[3];
    buf[2] = 0;

    std::stringstream input(wut);
    input.flags(std::ios_base::hex);
    while (input)
    {
        input >> buf[0] >> buf[1];
        long val = strtol(buf, nullptr, 16);
        datafile << static_cast<unsigned char>(val & 0xff);
    }

}

3
请注意!如果十六进制字符串中连续两个或多个'0'形成一串,则此方法不起作用!请查看我下面提供的另一个可能的解决方案,假设十六进制字符串长度为偶数,则可以保证100%的成功率。 - ElectRocnic
注意:最后一个字节多了一个零,导致文件损坏! - Emrexdy

3

@Peter R的答案会导致输出不完全相等,这是由于stringstream以意外的方式解释了多个连续的“0”。

例如:如果我们想写入十六进制值“00000000”,stringstream将输出“ 000000”。

下面的解决方案在每种情况下都有效,无论十六进制字符串中包含多少个零

// Input
std::string hex = "180f00005e2c3415"; // (or longer)

std::basic_string<uint8_t> bytes;

// Iterate over every pair of hex values in the input string (e.g. "18", "0f", ...)
for (size_t i = 0; i < hex.length(); i += 2)
{
    uint16_t byte;

    // Get current pair and store in nextbyte
    std::string nextbyte = hex.substr(i, 2);

    // Put the pair into an istringstream and stream it through std::hex for
    // conversion into an integer value.
    // This will calculate the byte value of your string-represented hex value.
    std::istringstream(nextbyte) >> std::hex >> byte;

    // As the stream above does not work with uint8 directly,
    // we have to cast it now.
    // As every pair can have a maximum value of "ff",
    // which is "11111111" (8 bits), we will not lose any information during this cast.
    // This line adds the current byte value to our final byte "array".
    bytes.push_back(static_cast<uint8_t>(byte));
}

// we are now generating a string obj from our bytes-"array"
// this string object contains the non-human-readable binary byte values
// therefore, simply reading it would yield a String like ".0n..:j..}p...?*8...3..x"
// however, this is very useful to output it directly into a binary file like shown below
std::string result(begin(bytes), end(bytes));

然后,您可以像这样将此字符串写入文件:
std::ofstream output_file("filename", std::ios::binary | std::ios::out);
if (output_file.is_open())
{
    output_file << result;
    output_file.close();
}
else
{
    std::cout << "Error could not create file." << std::endl;
}

它运行得很好,您介意解释一下逻辑吗? - Daniel Selvan
1
@DanielSelvan 添加了注释。 - ElectRocnic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接