字符串和十六进制数的相互转换
通过文件进行通信的,可能遇上的问题就是文件中的字符出现乱码的问题。在网上也找了很久资料,一般都是字符串转换成十六进制,很少有转换回来的。首先根据使字符集格式分为char和wchar_t两个版本
1. char版本
std::string string_to_hex(const std::string& input) { static const char* const lut = "0123456789ABCDEF"; size_t len = input.length(); std::string output; output.reserve(2 * len); for (size_t i = 0; i < len; ++i) { const unsigned char c = input[i]; output.push_back(lut[c >> 4]); output.push_back(lut[c & 15]); } return output; } std::string hex_to_string(const std::string& input) { static const char* const lut = "0123456789ABCDEF"; size_t len = input.length(); if (len & 1) throw std::invalid_argument("odd length"); std::string output; output.reserve(len / 2); for (size_t i = 0; i < len; i += 2) { char a = input[i]; const char* p = std::lower_bound(lut, lut + 16, a); if (*p != a) throw std::invalid_argument("not a hex digit"); char b = input[i + 1]; const char* q = std::lower_bound(lut, lut + 16, b); if (*q != b) throw std::invalid_argument("not a hex digit"); output.push_back(((p - lut) << 4) | (q - lut)); } return output; }
这是从stackoverflow上摘下来的,对于使用ASCII字符集的字符串来说没有什么问题,但对于使用2字节存储的字符就无能为力了。
2.wchar_t版本
CString ConvertWCHARToHex(CString Data) { CString sResult(""); int len = Data.GetLength(); for (long nLoop=0; nLoop<len; nLoop++) { wchar_t ch = Data.GetAt(nLoop); //将wchar_t转换为char[2] char c_cn[2]={'0'}; W2C(ch,c_cn); static const char *hex = "0123456789ABCDEF"; for(int i=0;i<2;i++) { unsigned char chHexA = hex[((unsigned char)(c_cn[i]) >> 4) & 0x0f]; unsigned char chHexB = hex[(unsigned char)(c_cn[i]) & 0x0f]; sResult += (char)chHexA; sResult += (char)chHexB; } } return sResult; }
void W2C(wchar_t w_cn, char c_cn[])
{
c_cn[0] = w_cn >> 8 ;
c_cn[1] = (char)w_cn ;
}
CString ConvertHexToWCHAR(CString Data) { wstring wstr; wstr.reserve(Data.GetLength() / 4); int i; for (i=0; i < Data.GetLength()/4; ++i) { int n_value = _tcstol(Data.Mid(i*4, 4), NULL, 16); wstr.push_back((wchar_t)n_value); } CString strResult(wstr.c_str()); return strResult; }
CString的Format方法能直接格式化成十六进制的字符,但对于使用UTF8的来说就有点问题。因为UTF8完美兼容ASCII,也就是使用单字节,对于其他的字符,比如汉字,使用的又是双字节,所以转换成的十六进制就很难判断源字符是来自于单字节字符还是双字节字符。
这里使用了CString,但对于不支持MFC的来说,重写一下也不是什么大问题。留到下次更新吧。