Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Writing hex to a file

Tags:

c++

string

file

hex

I have a program that reads the hex of a file, modifies it, and stores the modified hex in a std::string.

For example, how would I write this to a file

std::string wut="b6306edf953a6ac8d17d70bda3e93f2a3816eac333d1ac78";

and get its value

.0n..:j..}p...?*8...3..x

in the outputted file?

I'd prefer not to use sprintf, but I guess if it's necessary, I'll do what I must.

like image 600
Moon Avatar asked Feb 17 '14 02:02

Moon


2 Answers

If I understand your question correctly you want the text converted to it's numeric equivalent and then written to file. Given the hint you provided in your question it looks like this should be done byte by byte. Below is one way to achieve this. Note the need to convert each byte from a string to an integer value.

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

}
like image 148
Peter R Avatar answered Oct 31 '22 21:10

Peter R


The answer of @Peter R will lead to an output which is not 100% equal, due to the stringstream interpreting more than one '0's in a row in an unintended way.

Example: If we want to write the hex value "00000000", the stringstream would output " 000000".

The solution below works in every case, no matter how many zeros are contained in the hex string:

// 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));

Then you can simply write this string to a file like this:

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;
}
like image 28
ElectRocnic Avatar answered Oct 31 '22 21:10

ElectRocnic