WSLはWin32との文字コードの違いにどう対応しているか?
Windows Subsystem for Linux(WSL)には、Win32相互運用性と呼ばれる機能があり、WSLのbashから直接Win32プログラムを起動することができる。WSLのLinuxディストリビューションは、標準の文字コードとしてUTF-8を使うのに対して、Win32プログラムの標準の文字コードは、日本語版Windowsの場合ではShift-JISである。
しかし、WSLやCMD.EXE(コマンドプロンプトウィンドウ)では、お互いをパイプで接続してコマンドを連続して動作させることが可能だ。このときWSLは、コマンドラインを見て、Win32プログラムが適切な文字コードを出力できるように調整をおこなう。具体的には、以下の3つの場合が考えられる。
1. Win32プログラムの標準出力がコンソールに接続しているとき
2. Win32プログラムの標準出力がLinux側のコマンドの標準入力に接続しているとき
3. Win32プログラムが標準出力を利用していないとき(Win32 GUIアプケーションの場合)
「1」の場合、日本語版Windowsでは、Win32コマンドからはShift-JISコードを含んだ文字列が出力される可能性が高い。このときのWSLは、コンソールに出力される文字コードをUTF-8に変換して表示する。なお、現在のコンソールウィンドウは、内部でUTF-8コードを使っている。
「2」の場合、WSLはWin32コマンドが動作する環境を変更し、コードページに65001(UTF-8)を指定してWin32コマンドを起動する。これにより、Win32コマンドはUTF-8コード、実際にはメッセージが英語となり、ASCIIコードを出力する。UTF-8は、ASCIIコードの範囲では一致しており、この範囲の文字は正しく表示できる。
「3」の場合、WSLから標準入出力を使って直接データを渡すことはできず、必ずファイルを介したものになる。このため、WSL側で作られるUTF-8への対応は、アプリごとに違ってくる。たとえば、メモ帳はすでにUTF-8に対応しているため、WSL側のコマンドが出力したUTF-8のファイルをそのまま開くことが可能だ。
MS-DOS時代に作られたコードページって何?
コードページとは、MS-DOSの時代に作られたコンソールにおいて、複数言語を扱うためのものだ。現在Linuxなどで使う「ロケール」に似た概念だが、そもそも、ハードウェアで文字を表示させていた時代のものなので、文字コードを指定するものになっている。
コードページは数字で表現され、たとえば日本語のShift-JISを使う環境では932というコードページが使われる。これに対してオリジナルのIBM PCでは、コードページ437が使われている。もともとコードページ437は、IBM PC用のCGA~VGAなどのハードウェアで文字を表示させる環境のための文字コードでASCIIコードが基本。ただしハードウェア的には、0~255までの文字コードに表示可能な文字が対応しており、ビデオメモリに書かれたコードに対応した文字が表示される。当初のコードページは、ハードウェアのフォント(ビデオ回路のキャラクタジェネレーター)を区別するためのものだった。
その後のWindowsでは、TrueTypeなどのフォントを利用できるようになり、現在のコードページからは、フォントを指定するという意味は失われている。なので、コードページは437でも表示フォントはMSゴシックといった設定が可能である。Windows 10でも、ラスターフォントを指定すると、IBM PCが持っていたフォント(ASCIIコード外の文字を含む)を表示させることができる。
Windows 10のコンソールでは、個々のWindowsの標準的なコードページ以外も選択可能だが、その動作は実行するアプリケーションに依存する。サポートされているコードページの1つが65001で、この場合はコードエンコード方式にUTF-8が使われる。正しくUTF-8に対応したアプリケーションであれば、文字はUTF-8コードで出力される。しかし多くの場合、アプリケーションはメッセージを英語で出力する。これは、UTF-8とASCIIコードがASCII文字の範囲では一致しているからだ。
コードページは、日本語や同じ1バイトコードでもアルファベットに違いのあるヨーロッパ系の言語などに対応するために作られた。ただし、ソフトウェアの互換性を保つために、コードページや他国語をまったく考慮していないアプリケーションがあったときに、英語環境にも設定できるようになっていた。
コンソールのコードページは、chcpコマンド(C:\Windows\System32\chcp.com)で表示させることができる。これをWSLから起動すれば、実行環境のコードページを調べることができるはずだ。ただし、Windows 10 Ver.1809(RS5)の場合、標準出力に何も接続しない場合には、コードページとしてゼロが表示され、パイプ記号でmoreコマンド(Linuxのコマンド)と接続した場合には、65001が表示された。
ただし、Windows 10 Ver.1903(19H1)では、標準出力に何も接続しなかった場合には、932(日本語Shift-JIS)が表示されるようになった。このあたり、ちゃんと処理されるようになったようだ。chcpは、おそらくシステムコールでコードページを取得しているだけなので、Windows側の問題だと思われる。
このように、WSLでは、文字コードで問題が起きないように標準出力の状態を見て、コードページを切り替える。そのためコマンドを単独で実行させると、日本語が出るのに、パイプやリダイレクトでは英語メッセージとなることがある。
この連載の記事
-
第458回
PC
Windows上でhostsファイルを活用する -
第457回
PC
IPv6アドレスは先頭を見ればどんな種類かわかる -
第456回
PC
あらためてIPv6基本のキ -
第455回
PC
Windowsで現在どのネットワークアダプタがインターネット接続に使われているかを調べる方法 -
第454回
PC
Windows 11 24H2では「デバイスの暗号化」の条件が変わり、より多くのPCでドライブが暗号化される -
第453回
PC
Windows 11 24H2の配布開始後もすぐにはやってこない Windows UpdateとSafeguard Holds -
第452回
PC
Windows 11 Ver.24H2が登場 Copilot+ PCとそうでないPCで実質Windowsが2つに分かれる -
第451回
PC
新しいWindowsサンドボックスではコマンドラインからの制御が可能に -
第450回
PC
ユニコードで文字数を数える方法 -
第449回
PC
WSLはプレビュー版でGUIでの設定が加わった! リリース2.3.xの新機能を見る -
第448回
PC
PowerShellで面倒なオブジェクトはPSCustomObjectに変換するのが早道 - この連載の一覧へ