How to convert Byte Array to hex string in visual c++?

58,112

Solution 1

As you have mentioned c++, here is an answer. Iomanip is used to store ints in hex form into stringstream.

#include <sstream>
#include <iomanip>

std::string hexStr(BYTE *data, int len)
{
     std::stringstream ss;
     ss << std::hex;

     for( int i(0) ; i < len; ++i )
         ss << std::setw(2) << std::setfill('0') << (int)data[i];

     return ss.str();
}

Solution 2

This code will convert byte array of fixed size 100 into hex string:

BYTE array[100];
char hexstr[201];
int i;
for (i=0; i<ARRAY_SIZE(array); i++) {
    sprintf(hexstr+i*2, "%02x", array[i]);
}
hexstr[i*2] = 0;

Solution 3

Here is a somewhat more flexible version (Use uppercase characters? Insert spaces between bytes?) that can be used with plain arrays and various standard containers:

#include <string>
#include <sstream>
#include <iomanip>

template<typename TInputIter>
std::string make_hex_string(TInputIter first, TInputIter last, bool use_uppercase = true, bool insert_spaces = false)
{
    std::ostringstream ss;
    ss << std::hex << std::setfill('0');
    if (use_uppercase)
        ss << std::uppercase;
    while (first != last)
    {
        ss << std::setw(2) << static_cast<int>(*first++);
        if (insert_spaces && first != last)
            ss << " ";
    }
    return ss.str();
}

Example usage (plain array):

uint8_t byte_array[] = { 0xDE, 0xAD, 0xC0, 0xDE, 0x00, 0xFF };
auto from_array = make_hex_string(std::begin(byte_array), std::end(byte_array), true, true);
assert(from_array == "DE AD C0 DE 00 FF");

Example usage (std::vector):

// fill with values from the array above
std::vector<uint8_t> byte_vector(std::begin(byte_array), std::end(byte_array));
auto from_vector = make_hex_string(byte_vector.begin(), byte_vector.end(), false);
assert(from_vector == "deadc0de00ff");

Solution 4

Using stringstream, sprintf and other functions in the loop is simply not C++. It's horrible for performance and these kind of functions usually get called a lot (unless you're just writing some things into the log).

Here's one way of doing it. Writing directly into the std::string's buffer is discouraged because specific std::string implementation might behave differently and this will not work then but we're avoiding one copy of the whole buffer this way:

#include <iostream>
#include <string>
#include <vector>

std::string bytes_to_hex_string(const std::vector<uint8_t> &input)
{
  static const char characters[] = "0123456789ABCDEF";

  // Zeroes out the buffer unnecessarily, can't be avoided for std::string.
  std::string ret(input.size() * 2, 0);
  
  // Hack... Against the rules but avoids copying the whole buffer.
  auto buf = const_cast<char *>(ret.data());
  
  for (const auto &oneInputByte : input)
  {
    *buf++ = characters[oneInputByte >> 4];
    *buf++ = characters[oneInputByte & 0x0F];
  }
  return ret;
}

int main()
{
  std::vector<uint8_t> bytes = { 34, 123, 252, 0, 11, 52 };
  std::cout << "Bytes to hex string: " << bytes_to_hex_string(bytes) << std::endl;
}

Solution 5

how about using the boost library like this (snippet taken from http://theboostcpplibraries.com/boost.algorithm ):

#include <boost/algorithm/hex.hpp>
#include <vector>
#include <string>
#include <iterator>
#include <iostream>

using namespace boost::algorithm;

int main()
{
  std::vector<char> v{'C', '+', '+'};
  hex(v, std::ostream_iterator<char>{std::cout, ""});
  std::cout << '\n';

  std::string s = "C++";
  std::cout << hex(s) << '\n';

  std::vector<char> w{'4', '3', '2', 'b', '2', 'b'};
  unhex(w, std::ostream_iterator<char>{std::cout, ""});
  std::cout << '\n';

  std::string t = "432b2b";
  std::cout << unhex(t) << '\n';
}
Share:
58,112

Related videos on Youtube

Amit Pal
Author by

Amit Pal

A graduate from IIT(BHU)-Varanasi, India

Updated on July 09, 2022

Comments

  • Amit Pal
    Amit Pal almost 2 years

    Declaration of a method are following:

    //some.h
    void TDES_Decryption(BYTE *Data, BYTE *Key, BYTE *InitalVector, int Length);
    

    I am calling this method from the following code:

    //some.c
    extern "C" __declspec(dllexport) bool _cdecl OnDecryption(LPCTSTR stringKSN, LPCTSTR BDK){
        TDES_Decryption(m_Track1Buffer, m_cryptoKey, init_vector, len);
        return m_Track1Buffer;
    }
    

    Where as data type of m_Track1Buffer is BYTE m_Track1Buffer[1000]; Now i want to make some changes in above method i.e. want to return the String in hex instead of Byte. How should i convert this m_Track1buffer to Hex string

    • mvp
      mvp over 11 years
      What is hexagonal string? Did you mean hex string here? Please edit and clarify. Also, it is always helpful to give examples of input and expected output.
  • Amit Pal
    Amit Pal over 11 years
    Thanks for answering but how should i return it. what variable should i return here ?
  • Felix Dombek
    Felix Dombek about 10 years
    @AmitPal return something like std::string(hexstr)
  • jww
    jww over 9 years
    You need to pad with the '0' character using setfill('0').
  • IFeelGood
    IFeelGood almost 6 years
    I had also to add std::setw to have it works to output correctly 2 digit for each number. So now it looks like ss << std::hex << std:.setfill ('0'); and ss<<std::setw(2)<<static_cast<int>(data[i]);
  • Darrin Cullop
    Darrin Cullop over 5 years
    I'm not sure if you got downvoted because of Boost, but I think your answer is acceptable and should not have a negative score.
  • Steve Smith
    Steve Smith about 5 years
    This answer would be perfect if the comments were implemented.
  • Anssi
    Anssi over 4 years
  • Imtiaz Shakil Siddique
    Imtiaz Shakil Siddique almost 3 years
    This is much better than the expected solution. You can also remove the vector type input and use a pointer array instead. That'll make it even more minimal (requiring few libraries)
  • user1119279
    user1119279 about 2 years
    But also, static_cast<uint32_t>(static_cast<uint8_t>(data[i])) to support negative numbers (char is signed on many platforms)