Consoleの文字化け対策 CoreCLR

昨日のテストで、文字化けしていましたが、これを対策します。

答えは簡単で、エンコードの問題でした。

まず、コンソールのエンコードを見てみます。

932、Shift-JISとなっています。これに対して、System.Consoleのエンコーディングを見てみます。

UTF-8となっています。つまり、UTF-8として出力されたものをShift-JISとして表示しようとしているので、おかしくなっていると考えられます。あわせてしまえばよいですね。一人でやってる分にはConsoleのエンコードを変えるという選択肢もあるかもしれません。ただ、そうしてしまうと個々の環境で設定が必要になってしまうため、コード側で対策しておきたいところです。なので、System.Consoleのエンコードを変えてみます。

var enc = System.Text.Encoding.GetEncoding(932);
var writer = new System.IO.StreamWriter(Console.OpenStandardOutput(), enc);
Console.SetOut(writer);

としたいところなのですが、実はこれだと動きません。

NotSupportedException
No data is available for encoding 932. For information on defining a custom encoding, see the documentation for the Encoding.RegisterProvider method.

何やら、エラーがSystem.Text.Encoding.RegiterProviderメソッドを見ろといっています。ここの説明では

.NET Framework 4.61 つのエンコード プロバイダーが含まれています。 T:System.Text.CodePagesEncodingProvider、を行う、利用可能なエンコーディングでは使用できませんが、完全な .NET Framework に存在を.NET Framework 4.6です。既定では、.NET Framework 4.6のみ、Unicode エンコーディング、ASCII、およびコード ページ 28591 をサポートします。

この「のみ」にすこし違和感ありますが、日本語は含まれていないようです。28591は西ヨーロッパ言語 (ISO)ですね。というわけで、そもそも、日本語は既定でサポートされていません。デスクトップ同様のサポートを確保するためには、System.Text.CodePagesEncodingProviderを利用してねーという内容ですかね。このクラスには、Instanceという静的なプロパティが一つ。これをエラーの内容に従って追加してみましょう。

System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var enc = System.Text.Encoding.GetEncoding(932);
var writer = new System.IO.StreamWriter(Console.OpenStandardOutput(), enc);
Console.SetOut(writer);

という感じにしてみました。いざ、実行!

あれ!きれいですね。何も出てこないとなるのですが、これはバッファにFlushがかからないために出てこなくなるようです。なので、AutoFlushを有効にしちゃいましょう。

System.Text.Encoding.RegisterProvider(System.Text.CodePagesEncodingProvider.Instance);
var enc = System.Text.Encoding.GetEncoding(932);
var writer = new System.IO.StreamWriter(Console.OpenStandardOutput(), enc);
writer.AutoFlush = true;
Console.SetOut(writer);

という感じにプロパティの設定を追加。再び!

無事に日本語を拝めました。注意として、ここの実装だけだと、強制的にShiftJISとしてしまうので、Linuxで動かしたときは、逆に文字化けしてしまう可能性があります。また、日本語ではないWindowsでも同じことが言えます。様々なプラットフォームで動かすためには、以下を考慮しておいてみるとよいのではないかと思います。

  • 実行しているOSが、Windowsか?
  • 日本語で動いているか?
それでは!

 

BlackJumboDog on CoreCLR を.NetFrameworkで動かそうと思ったら・・・

ツイッターで、.NetFramework4.6で動かして、NUnitどうなの?という声をいただきまして、さっそく!project.jsonに以下を追加してみました。

  “frameworks”: {
“dnxcore50”: { },
“dnx461”: { }
}

う・・・。いやな感じに。

というのも、このSystem.Text.Encodingを含めは、23516で統一していたのですが、.netframework4.6では、どうやら違うバージョンになさいとのことです。バージョンを厳密にした思わぬ落とし穴でした。

(というか、、、少しおかしい気がします。機会があったらこの辺調べてみようかとは思います。dnx461でそもそもいいのとか。)

これを、それぞれのフレームワーク用に整えていけばよいのですが、今回の目的は、.NetFrameworkでも動かす!ではなく、テストの簡略化にありましたので、別の案を考えたほうがよさそうなところでもあります。

ただ、テストコードは、アプリケーションさえたたいてしまえばよいわけで・・・テストコードの結果さえ得られればよいわけで・・・という風にも考えられなくもないですね。

「NUnit dnx」とかぐぐっていたら、こんなものもありました。

https://github.com/xunit/dnx.xunit

Getting Started with xUnit.net (DNX / ASP.NET 5)

ちょっと興味が出てきます!これをNUnitのコードから移植してとかっていうのも面白そうですね!

(つづく