Unicode文字列をutf-8またはutf-16文字列に変換する方法は?
-
07-07-2019 - |
質問
Unicode文字列をutf-8またはutf-16文字列に変換する方法は? 私のVS2005プロジェクトはUnicode文字セットを使用していますが、cppのsqliteは
を提供しますint sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
int sqlite3_open16(
const void *filename, /* Database filename (UTF-16) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
フォルダを開くため。 文字列、CString、またはwstringをUTF-8またはUTF-16文字セットに変換するにはどうすればよいですか?
ありがとうございます!
解決
簡単な答え:
CStringやwstringなどのUnicode文字列を使用する場合、変換は不要です。 sqlite3_open16()を使用します。
WCHARポインター( void *
にキャストされている)を渡す必要があります。このlibがクロスプラットフォームであっても、プラットフォームに依存するワイドchar型を定義できたと思います。 APIの void *
)よりも使いにくい。 CStringなど:(void *)(LPCWSTR)strFilename
長い回答:
UTF8またはUTF16に変換するUnicode文字列がありません。与えられたエンコーディングを使用して、プログラム内でUnicode文字列が表現されています:Unicodeはそれ自体バイナリ表現ではありません。エンコーディングは、Unicodeコードポイント(数値)がメモリ(数値のバイナリレイアウト)でどのように表現されるかを示します。 UTF8およびUTF16は、最も広く使用されているエンコーディングです。しかし、それらは非常に異なっています。
VSプロジェクトが「Unicode文字セット」と言っている場合、実際には「文字はUTF16としてエンコードされている」ことを意味します。したがって、sqlite3_open16()を直接使用できます。変換は必要ありません。文字は、16ビットを取るWCHARタイプ( char
とは対照的に)に格納されます(Win32では16ビットを取る標準Cタイプ wchar_t
ではフォールバック)。プラットフォーム。修正をありがとう、チェッカー)。
注意が必要な詳細がもう1つあります。UTF16には、ビッグエンディアンとリトルエンディアンの2つのフレーバーがあります。これがこれらの16ビットのバイト順序です。 UTF16に指定する関数プロトタイプは、使用される順序を示していません。しかし、sqliteがWindowsと同じエンディアンを使用していると仮定すると、かなり安全です(リトルエンディアンIIRC。順序はわかっていますが、名前に常に問題があります:-))。
編集:チェッカーによるコメントへの回答:
UTF16は16ビットのコードユニットを使用します。 Win32(およびWin32ではのみ)では、このようなストレージユニットに wchar_t
が使用されます。トリックは、一部のUnicode文字では、このような2つの16ビットコード単位のシーケンスが必要になることです。それらはサロゲートペアと呼ばれます。
UTF8が1〜4バイトのシーケンスを使用して1文字を表すのと同じ方法。ただし、UTF8は char
タイプで使用されます。
他のヒント
WideCharToMultiByte 関数を使用します。 CodePage
パラメーターに CP_UTF8
を指定します。
CHAR buf[256]; // or whatever
WideCharToMultiByte(
CP_UTF8,
0,
StringToConvert, // the string you have
-1, // length of the string - set -1 to indicate it is null terminated
buf, // output
__countof(buf), // size of the buffer in bytes - if you leave it zero the return value is the length required for the output buffer
NULL,
NULL
);
また、WindowsのUnicodeアプリのデフォルトエンコーディングはUTF-16LEであるため、変換を実行する必要はなく、2番目のバージョン sqlite3_open16
を使用するだけです。
すべてのC ++文字列型は文字セット中立です。それらは文字幅に収まり、それ以上の仮定は行いません。 wstringはWindowsで16ビット文字を使用します。これはおおよそutf-16に対応しますが、それでもスレッドに保存するものに依存します。 wstringは、そこに入れるデータが有効なutf16でなければならないことを強制しません。 Windowsは、UNICODEが定義されている場合でもutf16を使用するため、ほとんどの場合、文字列はすでにutf16であり、何もする必要はありません。
他のいくつかはWideCharToMultiByte関数の使用を提案しています。これは、utf16をutf8に変換する方法の1つです。ただし、sqliteはutf16を処理できるため、これは必要ありません。
utf-8とutf-16は両方とも「ユニコード」です。文字エンコーディング。おそらくあなたが話すのは、固定サイズの文字エンコーディングであるutf-32です。たぶん検索
" utf-32をutf-8またはutf-16に変換"
これに関する結果やその他の論文を提供します。
これを行う最も簡単な方法は、CStringAを使用することです。 CStringクラスは、CStringA(ASCIIバージョン)またはCStringW(ワイド文字バージョン)のtypedefです。これらの両方のクラスには、文字列型を変換するコンストラクターがあります。私は通常使用します:
sqlite3_open(CStringA(L"MyWideCharFileName"), ...);