Converting a hex string to a byte array

后端 未结 19 1935
时光取名叫无心
时光取名叫无心 2020-11-22 12:10

What is the best way to convert a variable length hex string e.g. \"01A1\" to a byte array containing that data.

i.e converting this:

st         


        
相关标签:
19条回答
  • 2020-11-22 12:46

    i've modified TheoretiCAL's code

    uint8_t buf[32] = {};
    std::string hex = "0123";
    while (hex.length() % 2)
        hex = "0" + hex;
    std::stringstream stream;
    stream << std::hex << hex;
    
    for (size_t i= 0; i <sizeof(buf); i++)
        stream >> buf[i];
    
    0 讨论(0)
  • 2020-11-22 12:48

    C++11 variant (with gcc 4.7 - little endian format):

        #include <string>
        #include <vector>
    
        std::vector<uint8_t> decodeHex(const std::string & source)
        {
            if ( std::string::npos != source.find_first_not_of("0123456789ABCDEFabcdef") )
            {
                // you can throw exception here
                return {};
            }
    
            union
            {
                uint64_t binary;
                char byte[8];
            } value{};
    
            auto size = source.size(), offset = (size % 16);
            std::vector<uint8_t> binary{};
            binary.reserve((size + 1) / 2);
    
            if ( offset )
            {
                value.binary = std::stoull(source.substr(0, offset), nullptr, 16);
    
                for ( auto index = (offset + 1) / 2; index--; )
                {
                    binary.emplace_back(value.byte[index]);
                }
            }
    
            for ( ; offset < size; offset += 16 )
            {
                value.binary = std::stoull(source.substr(offset, 16), nullptr, 16);
                for ( auto index = 8; index--; )
                {
                    binary.emplace_back(value.byte[index]);
                }
            }
    
            return binary;
        }
    

    Crypto++ variant (with gcc 4.7):

    #include <string>
    #include <vector>
    
    #include <crypto++/filters.h>
    #include <crypto++/hex.h>
    
    std::vector<unsigned char> decodeHex(const std::string & source)
    {
        std::string hexCode;
        CryptoPP::StringSource(
                  source, true,
                  new CryptoPP::HexDecoder(new CryptoPP::StringSink(hexCode)));
    
        return std::vector<unsigned char>(hexCode.begin(), hexCode.end());
    }
    

    Note that the first variant is about two times faster than the second one and at the same time works with odd and even number of nibbles (the result of "a56ac" is {0x0a, 0x56, 0xac}). Crypto++ discards the last one if there are odd number of nibbels (the result of "a56ac" is {0xa5, 0x6a}) and silently skips invalid hex characters (the result of "a5sac" is {0xa5, 0xac}).

    0 讨论(0)
  • 2020-11-22 12:48

    Very similar to some of the other answers here, this is what I went with:

    typedef uint8_t BYTE;
    
    BYTE* ByteUtils::HexStringToBytes(BYTE* HexString, int ArrayLength)
    {
      BYTE* returnBytes;
      returnBytes = (BYTE*) malloc(ArrayLength/2);
      int j=0;
    
      for(int i = 0; i < ArrayLength; i++)
      {
        if(i % 2 == 0)
        {
          int valueHigh = (int)(*(HexString+i));
          int valueLow =  (int)(*(HexString+i+1));
    
          valueHigh = ByteUtils::HexAsciiToDec(valueHigh);
          valueLow =  ByteUtils::HexAsciiToDec(valueLow);
    
          valueHigh *= 16;
          int total = valueHigh + valueLow;
          *(returnBytes+j++) = (BYTE)total;
        }
      }
      return returnBytes;
    }
    
    int ByteUtils::HexAsciiToDec(int value)
    {
      if(value > 47 && value < 59)
      {
        value -= 48;
      }
      else if(value > 96 && value < 103)
      {
        value -= 97;
        value += 10;
      }
      else if(value > 64 && value < 71)
      {
        value -= 65;
        value += 10;
      }
      else
      {
        value = 0;
      }
      return value;
    }
    
    0 讨论(0)
  • 2020-11-22 12:50
    #include <iostream>
    #include <sstream>
    #include <vector>
    
    int main() {
        std::string s("313233");
        char delim = ',';
        int len = s.size();
        for(int i = 2; i < len; i += 3, ++len) s.insert(i, 1, delim);
        std::istringstream is(s);
        std::ostringstream os;
        is >> std::hex;
        int n;
        while (is >> n) {
            char c = (char)n;
            os << std::string(&c, 1);
            if(is.peek() == delim) is.ignore();
        }
    
        // std::string form
        std::string byte_string = os.str();
        std::cout << byte_string << std::endl;
        printf("%s\n", byte_string.c_str());
    
        // std::vector form
        std::vector<char> byte_vector(byte_string.begin(), byte_string.end());
        byte_vector.push_back('\0'); // needed for a c-string
        printf("%s\n", byte_vector.data());
    }
    

    The output is

    123
    123
    123
    

    '1' == 0x31, etc.

    0 讨论(0)
  • 2020-11-22 12:50

    In: "303132", Out: "012". Input string can be odd or even length.

    char char2int(char input)
    {
        if (input >= '0' && input <= '9')
            return input - '0';
        if (input >= 'A' && input <= 'F')
            return input - 'A' + 10;
        if (input >= 'a' && input <= 'f')
            return input - 'a' + 10;
    
        throw std::runtime_error("Incorrect symbol in hex string");
    };
    
    string hex2str(string &hex)
    {
        string out;
        out.resize(hex.size() / 2 + hex.size() % 2);
    
        string::iterator it = hex.begin();
        string::iterator out_it = out.begin();
        if (hex.size() % 2 != 0) {
            *out_it++ = char(char2int(*it++));
        }
    
        for (; it < hex.end() - 1; it++) {
            *out_it++ = char2int(*it++) << 4 | char2int(*it);
        };
    
        return out;
    }
    
    0 讨论(0)
  • 2020-11-22 12:51

    If your goal is speed, I have an AVX2 SIMD implementation of an encoder and decoder here: https://github.com/zbjornson/fast-hex. These benchmark ~12x faster than the fastest scalar implementations.

    0 讨论(0)
提交回复
热议问题