4

小さなutfcppライブラリを使用して、ワイドWindows API(FindFirstFileWなど)から取得したすべてのものをutf16to8を使用して有効なUTF8表現に変換するのは良い/安全/可能ですか?

内部でUTF8を使用したいのですが、正しい出力を取得できません(別の変換後のwcoutまたはプレーンcoutを介して)。もちろん通常のASCII文字は機能しますが、ñäはめちゃくちゃになります。

または、より簡単な代替手段はありますか?

ありがとう!

更新:Hans(下記)のおかげで、WindowsAPIを介してUTF8<->UTF16を簡単に変換できるようになりました。双方向変換は機能しますが、UTF16文字列からのUTF8には余分な文字がいくつかあり、後で問題が発生する可能性があります...)。純粋な親しみやすさからここで共有します:)):

// UTF16 -> UTF8 conversion
std::string toUTF8( const std::wstring &input )
{
    // get length
    int length = WideCharToMultiByte( CP_UTF8, NULL,
                                      input.c_str(), input.size(),
                                      NULL, 0,
                                      NULL, NULL );
    if( !(length > 0) )
        return std::string();
    else
    {
        std::string result;
        result.resize( length );

        if( WideCharToMultiByte( CP_UTF8, NULL,
                                 input.c_str(), input.size(),
                                 &result[0], result.size(),
                                 NULL, NULL ) > 0 )
            return result;
        else
            throw std::runtime_error( "Failure to execute toUTF8: conversion failed." );
    }
}
// UTF8 -> UTF16 conversion
std::wstring toUTF16( const std::string &input )
{
    // get length
    int length = MultiByteToWideChar( CP_UTF8, NULL,
                                      input.c_str(), input.size(),
                                      NULL, 0 );
    if( !(length > 0) )
        return std::wstring();
    else
    {
        std::wstring result;
        result.resize( length );

        if( MultiByteToWideChar(CP_UTF8, NULL,
                                input.c_str(), input.size(),
                                &result[0], result.size()) > 0 )
            return result;
        else
            throw std::runtime_error( "Failure to execute toUTF16: conversion failed." );
    }
}
4

2 に答える 2

7

Win32 APIには、これを行うための関数、CodePage = CP_UTF8を指定したWideCharToMultiByte()が既にあります。別のライブラリに依存する必要がなくなります。

通常、結果をwcoutで使用することはできません。その出力はコンソールに送られ、レガシーの理由で8ビットのOEMエンコーディングを使用します。SetConsoleCP()を使用してコードページを変更できます。65001はUTF-8(CP_UTF8)のコードページです。

次のつまずきは、コンソールに使用されるフォントです。変更する必要がありますが、固定ピッチで、Unicodeをカバーするためのグリフのフルセットを備えたフォントを見つけるのは困難です。出力に正方形の長方形が表示されると、フォントに問題があることがわかります。疑問符はエンコーディングの問題です。

于 2010-07-25T15:54:52.963 に答える
3

なぜUTF8を内部で使用したいのですか?UTF16を使用すると、不当なメモリ要求が発生するほど多くのテキストを処理していますか?その場合でも、とにかくワイド文字を使用し、他の方法(ディスクキャッシュ、より優れたアルゴリズム、またはデータ構造を使用)でメモリの問題に対処する方がよいでしょう。

コードは、Win32 APIにネイティブなワイド文字を内部的に使用し、それを必要とするデータ(XMLファイルやREST APIなど)の読み取りまたは書き込み時にのみUTF8変換を実行することで、はるかにクリーンで扱いやすくなります。

この問題は、出力をコンソールに出力する時点でも発生する可能性があります。「 WindowsコンソールアプリでのUnicode文字列の出力」を参照してください。

最後に、utfcppライブラリを使用していませんが、UTF8変換は、Win32を使用してコードページとして使用するのは非常にWideCharToMultiByte簡単MultiByteToWideCharですCP_UTF8。個人的には、必要に応じてUTF8で出力または転送するときまで、一度だけ変換を行い、UTF16のテキストを処理していました。

于 2010-07-25T15:52:44.707 に答える