1

とりわけ、さまざまなエンコーディングのさまざまな文字列を含むファイルを解析しています。これらの文字列の保存方法は次のとおりです。

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ます。

私が持っている2つの質問は次のとおりです。

  1. そのようなアプローチは合理的なものですか (つまり、boost::variant を使用します)?

  2. wstring特定の BOM を使用して作成するにはどうすればよいですか?

4

2 に答える 2

0

UTF16 は、LE と BE の間で区別する必要があります。

0x02 - utf-16 without BOM (wchar_t* directly)実際にはUTF16 BEだと思います。With BOMencoding は、LE/BE が BOM によって示されることを意味します。

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 を使用します。また、内部的に必要なテキスト エンコーディングは 1 つだけです。さらに、いくつかの変換関数で目的が果たせると思います。

于 2013-01-07T10:46:43.730 に答える
0

いくつかの調査、試行錯誤の後、utf8 との間で変換するための軽量でヘッダーのみの関数セットである UTF8-CPP を使用することにしました。utf-16 から utf-8 に変換する関数が含まれており、私の理解では、BOM を正しく処理できます。

次に、すべての文字列を として保存しstd::string、utf-16 文字列を utf-8 に変換します (上記の例から)。

整数の長さ; 文字エンコーディング; char* バイト;

string value;
switch(encoding) {
    case 0x00:
    case 0x03:
        value = string(bytes, length);
        break;
    case 0x01:
    case 0x02:
        vector<unsigned char> utf8;
        wchar_t* input = (wchar_t*)bytes;
        utf16to8(input, input + (length >> 1), back_inserter(utf8));
        value = string(utf8.start(), utf8.end());
        break;
    default:
        throw ERROR_INVALID_STRING_ENCODING;
}

これは私の簡単なテストではうまくいきます。最終判断の前に、さらにテストを行う必要があります。

于 2013-01-07T12:47:59.647 に答える