マイクロソフトは、製品にUnicodeを実装した最初の企業の1つでした。Windows NTは、システムコールで「ワイド文字」を使用した最初のオペレーティングシステムでした。当初は(現在では廃止された)UCS-2エンコーディング方式を使用していましたが、 Windows 2000以降は可変幅エンコーディングUTF-16にアップグレードされ、サロゲートペアによる追加プレーンの表現が可能になりました。しかし、マイクロソフトは2019年5月までUTF-8をサポートしていませんでした。
マイクロソフトの多くのドキュメントでは、「Unicode」という言葉は明確にUTF-16エンコーディングを指すために使用されています。UTF-8を含むそれ以外のものは、マイクロソフトの古い用語では「Unicode」ではありません(ただし、Unicode標準、またはそのエンコーディング/「変換フォーマット」によれば、UTF-8とUTF-16はどちらもUnicodeです)。
現在の Windows バージョンと、Windows XPおよびそれ以前のWindows NT (3.x、4.0) までのすべてのバージョンには、2 種類の文字列エンコーディングをサポートするシステム ライブラリが同梱されています。16 ビットの「Unicode」(Windows 2000以降はUTF-16)と、「コード ページ」(または誤ってANSIコード ページと呼ばれる)と呼ばれる (場合によってはマルチバイト) エンコーディングです。16 ビット関数の名前には、`w` ( `wide`から) という接尾辞が付きます。コード ページ指向の関数には、`ANSI` を表す接尾辞 `A` が付きます(他のシステムからコピーされた API には、`a` や`a`など、別の規則が使用されていました)。この分割が必要だったのは、 Cを含む多くの言語では、8 ビットと 16 ビットの両方の文字列を同じ関数に渡すためのきれいな方法が提供されていなかったためです。SetWindowTextWSetWindowTextA_wfopen/fopenwcslen/strlen
Microsoft は、コンパイラに「UNICODE」スイッチを提供することで Unicode を「移植性高く」サポートしようと試みました。このスイッチは、接尾辞のない「汎用」呼び出しを「A」インターフェースから「W」インターフェースに切り替え、すべての文字列定数を「ワイド」UTF-16 バージョンに変換します。[ 1 ] [ 2 ]これは、文字列定数以外の UTF-8 を変換しないため、実際には機能しません。結果として、ファイルを開こうとするコードがコンパイルされません。
以前、そして「UNICODE」スイッチとは別に、Windows はマルチバイト文字セット (MBCS) API スイッチも提供していました。[ 3 ]これにより、MBCS では動作しない関数 (例えば ) が、strrevMBCS に対応した関数 (例えば ) に変更されます_mbsrev。[ 4 ] [ 5 ]
(現在はサポート終了している)Windows CEでは、UTF-16 がほぼ独占的に使用され、「A」 API はほとんど欠落していました。[ 6 ] Windows CE 5.0では、限られたセットの ANSI API が利用可能で、ランタイム イメージに選択的に組み込むことができる限られたロケールで使用できます。[ 7 ]
2001 年、マイクロソフトは、マイクロソフトの古いWindows 9xシステム向けに特別な補足資料をリリースしました。これは、「ソフトウェア開発者がアプリケーションの単一の Unicode バージョンを作成し、すべてのプラットフォームで正しく実行できるように、Windows 95/98/Me のWin32 APIの上にレイヤーを提供する」と説明されていました。 [ 8 ] これには、Windows API のすべての基本関数の 16 ビット版 (末尾に文字 W が付いているもの) を含む動的リンク ライブラリ「unicows.dll」(わずか 240 KB) が含まれています。これは単なる変換レイヤーです。Windows 9x では、SetWindowTextW現在のコード ページを使用して入力を変換して呼び出しますSetWindowTextAが、Windows NT システムでは、OS バージョンの に渡されますSetWindowTextW。
代替案も存在し、その中には、 Mozillaによる MSLU のフリー( MPL 1.1/ GPL 2.0/ LGPL 2.1 ライセンス) の再実装であるOPENCOW.DLL、「The Open Layer for Unicode for Windows」などがあります。UNICOWS.LIBリンク ライブラリのオープンソース バージョンも利用可能で、オリジナルのUNICOWS.DLLまたはOPENCOW.DLLと一緒に使用できます。[ 9 ]
Microsoft Windows ( Windows XP以降) には、 UTF-8用に指定されたコードページ 65001 [ 10 ]または がありますCP_UTF8。長い間、ロケール コード ページを 65001 に設定することは不可能で、このコード ページは a) MultiByteToWideChar などの明示的な変換関数、および/または b) stdin/out を UTF-8 と UTF-16 間で変換するWin32 コンソールコマンドでのみ使用可能でした。これは、特に(ファイルを開く) などの「狭い」関数を UTF-8 文字列で呼び出すことができず、実際には、使用可能なロケールのいずれもすべての可能な UTF-16 文字を生成できないため、ロケールが何に設定されていても、および/または文字列にどのようなバイトが入れられていても、を使用してすべての可能なファイルを開く方法がなかったことを意味します。この問題は、Windows の API など、8 ビット文字列を受け取ったり返したりする他のすべての API にも適用されました。chcp 65001fopenfopenSetWindowText
UTF-8 を使用したいプログラム、特に他のオペレーティングシステムに移植することを目的としたコードでは、この欠点を回避する必要がありました。一般的な回避策は、MultiByteToWideChar を使用して UTF-8 を UTF-16 に変換する新しい関数をファイルを開くように追加し、代わりに「wide」関数を呼び出すことでしたfopen。[ 11 ]数十のマルチプラットフォームライブラリが、Windows でこの変換を実行するラッパー関数を追加しました (他のプラットフォームでは UTF-8 をそのまま渡します)。例として、Boost に追加される予定の Boost.Nowide があります。[ 12 ]もう1つの一般的な回避策は、名前を8.3 ファイル名相当に変換することでした。これは、がライブラリ内にある場合に必要です。これらの回避策はいずれも、Windows 以外の環境で動作するコードに変更を加える必要があるため、良い方法とは見なされていません。fopen
2018 年 4 月 (または 2017 年 11 月[ 13 ]の可能性もあります)、 Windows 10の Insider ビルド 17035 (通常ビルド 17134) で、ロケール コード ページを UTF-8 に設定するための「ベータ: 世界共通の言語サポートに Unicode UTF-8 を使用する」チェックボックスが表示されました。[ a ]fopenこれにより、UTF-8 文字列を使用して、やなどの「狭い」関数を呼び出すことができますSetWindowTextA。ただし、これはシステム全体の設定であるため、プログラムはそれが設定されていることを前提とすることはできません。
2019 年 5 月、マイクロソフトはプログラムがコード ページを UTF-8 に設定する機能を追加しました。[ 14 ] [ 15 ]これにより、UTF-8 を使用するように作成されたプログラムを専門知識のないユーザーでも実行できるようになりました。現在サポートされているすべてのコンシューマー向けバージョンの Windows は、この方法で UTF-8 をサポートしています。また、最近の Enterprise バージョン、Windows Server 2019以降、および Windows 10 IoT Enterprise 2021 LTSC なども同様です。
2019年現在Microsoft は、プログラマーに (少なくとも一部のケースでは) Windows とXboxでUTF-8 を使用することを推奨しており[ 14 ]、「UTF-8 は国際化のためのユニバーサル コード ページであり、UTF-16 は、複数のプラットフォームを対象とするコードに Windows が課す特有の負担である」と述べています[ 16 ] 。Microsoftは、以前は代替案を強調していたと述べ、UTF-8 への移行を進めているようで、Windows 11では一部のシステム ファイルは UTF-8 を使用する必要があり[ 17 ] 、UTF-8 であることを示すために先頭にUTF-8 バイト オーダー マーク(BOM)は必要ありません。メモ帳は、BOM なしで UTF-8 を認識できるようになり、BOM なしで UTF-8 を書き込むように指示できます。Visual Studio [ 18 ] [ 19 ]やSQL Server 2019など、他の Microsoft 製品も内部的に UTF-8 を使用しており、Microsoft は UTF-8 の使用により速度が 35% 向上し、「ストレージ要件がほぼ 50% 削減される」と主張しています。[ 20 ]
2019 年より前、Microsoft のコンパイラは UTF-8 ソース ファイルから UTF-8 文字列定数を生成できませんでした。これは、すべての文字列をロケール コード ページ (UTF-8 にはなり得ない) に変換していたためです。かつては、この問題を回避する唯一の方法は、UNICODE を無効に し、入力ファイルを UTF-8 としてマークしないこと(つまり、BOM を使用しないこと) でした。[ 21 ] これにより、コンパイラは入力と出力の両方が同じシングル バイト ロケールにあると認識し、文字列は変更されません。
当社のアプリケーションは、Windows関数の「A」バージョンを含むDBCS Windowsコードページを使用します。
再コンパイルする必要がある場合があります。
1903 (2019 年 5 月更新)
以降では
、パッケージ化されたアプリの場合は appxmanifest、パッケージ化されていないアプリの場合は fusion マニフェストの ActiveCodePage プロパティを使用して、プロセスに UTF-8 をプロセス コード ページとして使用するように強制できます。[...] これは、
Windows バージョン
1903 (2019 年 5 月更新) 以降で実行され、上記の ActiveCodePage プロパティが UTF-8 に設定されている場合にのみ
有効です
。それ以外の場合は、従来のシステム コード ページが適用されます。明示的に使用することをお勧めします
。
CP_ACPCP_UTF8CP_UTF8
-8 で動作することで、最大限の互換性を確保できます [..] Windows はネイティブでは UTF-16 (または WCHAR) で動作するため、MultiByteToWideChar および WideCharToMultiByte を使用してコード ページ変換を行う必要があります。これは、複数のプラットフォームを対象とするコードに対して Windows が課す特有の負担です。 [..] Microsoft Game Development Kit (GDK) および Windows 全般は、複数のプラットフォームや Web を対象とするコードやそれらとの交換における Windows 特有の負担を取り除くために、UTF-8 のサポートに向けて進んでいます。また、これにより、アプリやゲームにおける国際化の問題が減り、正しく動作させるために必要なテスト マトリックスも削減されます。
で UTF-8 エンコーディングが使用されていることを確認してください。
のある時点で、Microsoft コンパイラは内部的に UTF-8 を使用するように変更されました。そのため、ディスクからファイルが読み込まれると、その場で UTF-8 に変換されます。
Visual Studio は、ソース文字セットと実行文字セット間の変換時に、内部文字エンコーディングとして UTF-8 を使用します。
たとえば、UTF-8 が有効になっている照合順序を使用して既存の列のデータ型を NCHAR(10) から CHAR(10) に変更すると、ストレージ要件が 50% 近く削減されます。[..] ASCII 範囲では、UTF-8 で集中的な読み取り/書き込み I/O を実行すると、文字列列に非クラスター化インデックスを持つクラスター化テーブルを使用した場合、UTF-16 と比較して平均 35% のパフォーマンス向上、ヒープを使用した場合、UTF-16 と比較して平均 11% のパフォーマンス向上が測定されました。