前のエントリたちのさらに続き。
これらのエントリで、
外部のプロセスを呼び出し
標準出力(StdOut)
へ出力されたデータは最終的にString[]
型に変換されてStandard output stream
に出力される様です。
と言った内容を実際に確かめてみます。
検証プログラム
今回も簡単な検証プログラムOutput.exe
を用意しました。
using System; using System.Text; namespace Output { class Program { static void Main(string[] args) { // 標準出力に渡すバイト列を随時変えていく var Buffer = System.Text.Encoding.ASCII.GetBytes("Hello!"); var StdOut = Console.OpenStandardOutput(); StdOut.Write(Buffer, 0, Buffer.Length); } } }
このプログラムはBuffer
に設定したバイト列を標準出力に書き出すだけのものになります。
本エントリではこのBuffer
の部分を随時変えたOutput.exe
を用意して検証を進めていきます。
Standard output streamは標準出力から何を受け取っているのか?
まずは、Buffer
の部分を
var Buffer = System.Text.Encoding.ASCII.GetBytes("Hello!");
としたASCIIコードでHello!(48 65 6C 6C 6F 21)
を出力した結果を見てみます。
# [Console]::OutputEncoding = [Text.Encoding]::Default # var Buffer = System.Text.Encoding.ASCII.GetBytes("Hello!"); PS C:\Temp> $Output = .\Output.exe PS C:\Temp> $Output Hello! PS C:\Temp> $Output.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object
外部プロセスの結果$Output
はString
型のHello!
となりました。
ちなみに、前のエントリで使ったGetPipeline.exe
を使って外部プロセス間でパイプラインを繋ぐとどんなデータが渡されるかを見てみると以下の図の様になります。
上がコマンドプロンプト(Cmd.exe)で繋いだとき、下がPowerShellで繋いだ時になります。
PowerShellで繋ぐと一旦Standard output stream
に乗るため改行コードCRLF(0D 0A)
が付与されていることがわかります。
続けて、Buffer
の部分を
var Buffer = System.Text.Encoding.Default.GetBytes("あ");
としたMS932のあ(82 A0)
を出力した結果を見てみます。
# [Console]::OutputEncoding = [Text.Encoding]::Default # var Buffer = System.Text.Encoding.Default.GetBytes("あ"); PS C:\Temp> $Output = .\Output.exe PS C:\Temp> $Output あ PS C:\Temp> $Output.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object
こちらの場合も特に問題なくString
型のあ
となりました。
ここで[Console]::OutputEncoding = [Text.Encoding]::ASCII
に変更するとどうなるか見てみます。
# var Buffer = System.Text.Encoding.Default.GetBytes("あ"); PS C:\Temp> [Console]::OutputEncoding = [Text.Encoding]::ASCII PS C:\Temp> $Output = .\Output.exe PS C:\Temp> $Output ?? PS C:\Temp> $Output.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object
となり、文字化けした状態の文字列??
となってしました。
この後で[Console]::OutputEncoding = [Text.Encoding]::Default
に戻しても、
PS C:\Temp> [Console]::OutputEncoding = [Text.Encoding]::Default PS C:\Temp> $Output ??
となり、あ
ではなく??
としてStandard output stream
に渡されてしまっていることがわかります。
この結果からStandard output stream
は[Console]::OutputEncoding
でエンコードされた文字列を受け取っていることがわかります。
補足
ちなみに、適当なバイナリデータを渡しても[Console]::OutputEncoding
でエンコードした結果の文字列を受け取ります。
また、改行ありの文字列を受け取るとString[]
型(PowerShell上はObject[]
扱いとなる)として受け取ります。
var Buffer = System.Text.Encoding.Default.GetBytes("1行目\n2行目");
で試してみると、
# [Console]::OutputEncoding = [Text.Encoding]::Default # var Buffer = System.Text.Encoding.Default.GetBytes("1行目\n2行目"); PS C:\Temp> $Output = .\Output.exe PS C:\Temp> $Output 1行目 2行目 PS C:\Temp> $Output.GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True Object[] System.Array PS C:\Temp> $Output[0].GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object PS C:\Temp> $Output[1].GetType() IsPublic IsSerial Name BaseType -------- -------- ---- -------- True True String System.Object
といった結果になります。