UTF-8とUTF-16の違い
UTF-8
UTF-8は世界中の文字を表現するための文字コードとして、最も一般的に利用されるようになりました。Webページのファイル(HTML)などは、UTF-8が一般的であり、W3Cも『UTF-8は、ユニコードのやり取りに、最も適切なエンコーディング』としています(📌)。1文字のバイト数は可変長です。ASCIIと完全互換があります。ASCIIは文字コードでもあり、文字集合でもあります。
UTF-16
UTF-16はUTF-8と比べると有名ではないです。しかしながら、Windows OSにおけるアプリ内部の核となるライブラリ「Windows API」などでは、文字列を保持する形式はUTF-16が標準となっています(📌)。MFCのCString型における文字列もUTF-16となっています。
UTF-8とUTF-16の比較
組み込みエンジニア向けに、UTF-8とUTF-16の決定的な違いを次の表にまとめました。LE(Little Endian)はリトルエンディアン略称です。
UTF-8 |
UTF-16(LE) |
|
|---|---|---|
| 1文字のバイト数 | 1~4バイト | 2バイト(例外として4バイト) |
文字「あ」のコード |
E3 81 82 |
42 30 |
文字「い」のコード |
E3 81 84 |
44 30 |
文字「a」のコード |
61 |
61 00 |
文字「😀」のコード |
F0 9F 98 80 |
3D D8 00 DE |
サロゲートペア(UTF-16のみ)
サロゲートペアとは、「2バイトで表現できない文字を、2バイトのコードを2つセットで1文字を表す場合のペア」です。基本的にUTF-16では、2バイトのコードで日本語、英語、韓国語、中国語、およびその他の外国語の現代使用される文字のほとんどをカバーしています。しかし一部の文字は、2バイトのコードを2つ利用して、1文字 = 4バイトで表現します。
サンプルコード
次のプログラムは、Visual Studioで作成できるWindowsデスクトップアプリ開発用ライブラリ「MFC」にて、CString型の変数がUTF-16形式であることを確認するためのものです。
クラス「CDialogEx」を継承するクラス「CEncodingDlg」のダイアログリソース上のボタンがクリックされたときのイベント処理関数です。この関数は、『CString型変数がUTF-16でデータを管理すること』を確認するためのものです。
void CEncodingDlg::OnBnClickedButton1()
{
CString strText = _T("あいうえお");
// ■ CString型(UTF-16)のエンコーディングの確認
OutputDebugString(strText + _T("\r\n"));
// ■ CString型がUTF-16形式であることの確認
OutputDebugString(_T("---CString型がUTF-16であることの確認---\r\n"));
const wchar_t* pw = strText.GetString();
for (int i = 0; i < strText.GetLength(); i++)
{
CString strLog;
strLog.Format(_T("pw[%d] : 0x%04x\r\n"), i, pw[i]);
OutputDebugString(strLog);
}
// ■ CString(UTF-16) → char*(UTF-8)の変換
char* utf8 = CStringToUtf8(strText);
delete[] utf8;
utf8 = nullptr;
// ■ wchar_t配列のエンコーディングの確認
OutputDebugString(_T("---wchar_t型の配列のエンコーディングの確認---\r\n"));
wchar_t text[] = L"あいうえお";
int count = sizeof(text) / sizeof(wchar_t);
for (int i = 0; i < count; i++)
{
CString strLog;
strLog.Format(_T("text[%d] : 0x%04x\r\n"), i, text[i]);
OutputDebugString(strLog);
}
// ■ wchar_t型の配列からCString型変数を作成
OutputDebugString(_T("---wchar_t型の配列からCString型変数を作成---\r\n"));
CString strC(text);
OutputDebugStringW(strC + _T("\r\n"));
// ■ uint16_t型の配列からCString型変数を作成
OutputDebugString(_T("---wchar_t型の配列からCString型変数を作成---\r\n"));
uint16_t ushort_data[] = { 0x3053, 0x3093, 0x3070, 0x3093, 0x306F, 0x0000 };
CString strU((wchar_t*)ushort_data);
OutputDebugStringW(strU + _T("\r\n"));
}
あいうえお
---CString型がUTF-16であることの確認---
pw[0] : 0x3042
pw[1] : 0x3044
pw[2] : 0x3046
pw[3] : 0x3048
pw[4] : 0x304a
---wchar_t型の配列のエンコーディングの確認---
text[0] : 0x3042
text[1] : 0x3044
text[2] : 0x3046
text[3] : 0x3048
text[4] : 0x304a
text[5] : 0x0000
---wchar_t型の配列からCString型変数を作成---
あいうえお
---wchar_t型の配列からCString型変数を作成---
こんばんは