我正在解析一个文件,其中包含不同编码的各种字符串。这些字符串的存储方式是这样的:
0xFF 0xFF - block header 2 bytes
0xXX 0xXX - length in bytes 2 bytes
0xXX - encoding (can be 0, 1, 2, 3) 1 byte
... - actual string num bytes per length
通常这很容易,但是我不确定如何处理编码。编码可以是以下之一:
0x00 - regular ascii string (that is, actual bytes represent char*)
0x01 - utf-16 with BOM (wchar_t* with the first two bytes being 0xFF 0xFE or 0xFE 0xFF)
0x02 - utf-16 without BOM (wchar_t* directly)
0x03 - utf-8 encoded string (char* to utf-8 strings)
我需要以某种方式读取/存储。最初,我在考虑简单的
string
,但不适用于wchar_t*
。然后我想到了将所有内容转换为wstring
的方法,但这将是不必要的转换。接下来要想到的是boost::variant<string, wstring>
(我已经在代码的另一个地方使用了boost::variant
)。在我看来,这是一个合理的选择。因此,现在我有点无法解析。我正在按照以下思路思考://after reading the bytes, I have these:
int length;
char encoding;
char* bytes;
boost::variant<string, wstring> value;
switch(encoding) {
case 0x00:
case 0x03:
value = string(bytes, length);
break;
case 0x01:
value = wstring(??);
//how do I use BOM in creating the wstring?
break;
case 0x02:
value = wstring(bytes, length >> 1);
break;
default:
throw ERROR_INVALID_STRING_ENCODING;
}
由于我以后只需要打印这些字符串而已,因此我可以将UTF8存储在简单的
string
中,而不会造成太多麻烦。我有两个问题:
这样的方法是否合理(即使用boost :: variant)?
如何使用特定的BOM表创建
wstring
? 最佳答案
需要区分LE与BE之间的UTF16。
我怀疑实际上是UTF16 BE。 0x02 - utf-16 without BOM (wchar_t* directly)
编码表示BOM指示LE / BE。
C ++标准库对Unicode的支持非常有限,我不认为普通C ++会正确处理UTF16LE / BE,更不用说UTF8了。许多Unicode应用程序使用第三方支持库,例如ICU。
对于内存表示,我会坚持使用std :: string。因为std :: string可以表示任何文本编码,而std :: wstring对于这种多重编码情况没有太大帮助。如果您需要使用std :: wstring和相关的std :: iostream函数,请注意系统区域设置和std :: locale设置。
Mac OS X使用UTF8作为唯一的默认文本编码,而Windows使用UTF16 LE。我认为,您内部也只需要一种文本编码,再加上几种转换功能就可以达到目的。
关于c++ - 读取/存储不同类型的字符串(utf8/utf16/ansi),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14193800/