我正在解析一个文件,其中包含不同编码的各种字符串。这些字符串的存储方式是这样的:

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/

10-10 04:16