powershellがchcpでUTF-8対応という話でしたが、どうもおかしいのです。仕様書も見つけられないし振る舞いもあやしい。コマンドプロンプトの方が理解できる振る舞いをします。WindowsはウェブブラウザがOSの一部だと主張しながら、まともなエディタを作りませんでした。DOSの上にWindowsを乗せているのではなく、GUIでコントロールする一体のOSだと言ってコマンドプロンプトを旧態のままにしておいて、突然powershellなるものを出してきました。0213対応をしましたが、他国版と共通にUnicodeを使うようにしたということです。0213が必要ならばそれを使うことにしたのです。コマンドプロンプトはMS932のままに残されました。0213に対応していると期待をシたのですが、やっぱりだめだったということでした。それに比べるとLinuxの仮想端末は立派になっていると思います。2019年10月下旬のお話です。発端はJava普段はLinux上でプログラムを書いていますが、事情があってWindows10でコンパイルと実行ができることを確認する作業をしました。ところがうまくいきません。問題はサロゲートペアでした。Windowsでの確認とは、html文書に書いたプログラムをコピー&ペーストでエディタに取り込んで保存し、powershell上でJDKでのコンパイルと実行です。自然とShift_JISでの保存になり、そのままjavacコマンドで処理され、javaコマンドで実行するということで、いままで問題が起こったことはありません。今回のプログラムは、サロゲートペアを含む文字列を一文字ずつ取り出して処理をするものでした。WindowsのShift_JISではサロゲートペアを使うような文字を処理できないのです。10年以上Linuxメインでしたので、すっかり忘れていました。原因はJavaではなくエディタです。正しくUTF-8で保存できるエディタを使って、コンパイラにUTF-8を指示して、CUIへの文字としての表示は諦める。chcpというコマンドがあることを知りました。して文字表示もできるかもと思ったのが今回のハマりどころです。本来はこうなるはずだったいかにWindowsでもブラウザはUTF-8で書かれたページも正しく表示されますから、次はエディタがUTF-8で正しく保存できるかということです。私が昔からWindowsで使ってきたエディタはUTF-8で保存できるのですが、残念ながら内部の処理がShift_JISで、それに含まれない文字は??としてしまいます。結局Linuxで使っているgeditのWinndows版をインストールして使いました。LinuxからWindowsに移植されるソフトは増えてます。Javaは置かれた環境でのデフォルトの文字コードを感知してコンパイルします。Shift_JIS環境でソースコードがUTF-8の時には次のようにすれば良いことになっています。hogehoge.java作成されるクラスファイルはソースの文字コードによらず同じものができます。hogehoge.javaで、出力が環境に合わせて自動的にShift_JISになるので、普通は問題なく表示されます。今回はサロゲートペアの文字が含まれるので、この最後の表示部分が問題になるのです。ちなみに、原因がサロゲートペアのように書いていますが、正確にはちょっと違います。部分のみを含みますが、一般的にはMS932と同等に受け取られます。完全に網羅するShift_JISX0213もあり、面倒です。含まれず、また含まれるものも登録位置が変更になっていて、これがWindowsがShift_JISX0213に移行できなかった理由と思います。いうことなので、サロゲートペアでなくてもMS932で表現できない文字がたくさんあります。サロゲートペアを必要とする文字は少数です。MS932で表示できない所を確認まず、Javaプログラムで表示してみる。コンパイルのやり方と、サロレートペアに限らず、JISX0213で追加された文字が表示できないことが確認できる。os.nameなどは実行環境を残すために加えている。ms932で文字に起こしておきます。powershellのデフォルトの文字コードはMS932です。Javaの前にtypeコマンドでの表示で確認します。そのために2つのテキストファイルを用意します。ms932.txt(MS932で保存)。これはMS932で表現できる文字だけです。略で、引数なしだと現在の様子が表示されます。ms932.txtaaaaMS-932-cat|type0208:東西南北IBME:杦樰鉧銧UTF-8のファイルをMS932として表示するわけで、文字化けします。画面に出たものをそのままコピーして貼り付け、UTF-8で保存したもので全く同じに再現できているかはわかりませんが、雰囲気は似ています。utf8.txtaaaaUTF-8-cat|type0208:譚ア隘ソ蜊怜圏IBME:譚ヲ讓ー驩ァ驫ァ0213:蝗ィ濶ケ霎カ魏・surr:愚。或クス覧Javaは内部のUTF-16のデータをMS932に変換して表示するので、この表示とは異なります。65001で表示がUTF-8なるという話です。65001を打つと画面がクリアされるので、上のようには残りません。ms932.txtaaaaMS-932-cat|type0208:東西南北IBME:杦樰鉧銧おやおや変わりません。utf8.txtaaaaUTF-8-cat|type0208:譚ア隘ソ蜊怜圏IBME:譚ヲ讓ー驩ァ驫ァ0213:蝗ィ濶ケ霎カ魏・surr:愚。或クス覧UTF-8も同様です。身内の出す表示が変わらないというのは奇妙です。powershellの65001でJavaではJavaを使ってみます。cp650010208:kIBME:0213:????surr:????漢字が表示されません。Java側としてはpowershellがUTF-8環境であると理解してUTF-8で出すか、変更が理解されずにMS932のまま出すかのどちらかですが、どちらにしてもこの表示は理解できません。このために漢字部分の上のシステムプロパティを用意しました。chcpによって「sun.stderr.encoding」が変化したことが見て取れます。stderrというのが気になれます。プロパティに設定されているという情報があります。なっていますから、変更が理解されずにMS932として出力している可能性を考え、出力をUTF-8にするように指示してみます。CodePageTestSJW813S出力が一切なくなります。ASCII部分も含めて全部です。オプションの中のドットが悪さをしているようです。cp650010208:東西南北IBME:杦樰鉧銧0213:囨艹辶鰙surr:𠀋𡈽𩸽𡗗CodePageTestU8W8I3Sの後ろにスベースがたくさん入りos.nameが続けて入ってしまいます。上記は修正しています。サロゲート部分はコピーしてUTF-8に貼り付けた時点で漢字になります。javacのオプションは-encodingでjavaは-Dfile...ですが、これはコマンドの-helpで確認できます。システム・プロパティを設定するとあります。システム・プロパティが上記のプログラムにあったfile.encodingやsun.stderr.encodingだというわけです。ちなみに、コンパイルもUTF-8を指定しなければだめです。このファイルはUTF-8で書かれています。0208の部分とIBMEの部分ではエラーになっていないのがちょっと不思議ではあります。指定することで正しくコンパイルされ、上記のようにして実行できます。''の位置を変えてみました。ドットが問題のようです。cp650010208:東西南北IBME:杦樰鉧銧0213:囨艹辶鰙surr:𠀋𡈽𩸽𡗗キャプチャ画像も残しておきます。65001でpowershellのまとめtypeの動作が65001の触れ込みとは異なり、MS932のままのような印象を受けるJavaの出力をUTF-8にするとうまく表示されたことから、powershellの表示はUTF-8になっていて、Javaにはそれが伝わらずにいると考えると辻褄が合う。typeの結果と矛盾する。昨日はなかなか辻褄の会う結果が出ず、今日になってうまく行くようになった。