PowerShell 6で、Shift_JISのCSVをImport-Csvで読み込んだら文字化けした
Follow @venividivici830
PowerShell 4で作ったShift_JIS(シフトJIS)のCSVを読み込むスクリプトを、PowerShell 6で動かしたら文字化けした話。
結論としては、下記のようにすればOK。
> Import-Csv -Encoding ([System.Text.Encoding]::GetEncoding(932)) path_to_csv_file
ところが、PowerShell 6では上手くいかない。
例えば、下記のようなshift-jisのCSVがある。
これを、-Encoding defaultオプションで読み込むと、
このように文字化けする具合だ。
.NET Framework クラスライブラリーの、System.Text名前空間の、Encodingクラスの、Defaultプロパティーを確認した。
PowerShell 4では、-Encoding defaultでshift-jisとして読み込んでいたが、PowerShell 6では、utf-8として読み込まれるため、文字化けしたと思われる。
このページに、
Import-Csv [[-Path] <string[]>] [[-Delimiter] <char>] [-LiteralPath <string[]>] [-Header <string[]>] [-Encoding <Encoding>] [<CommonParameters>]
Encodingクラスのドキュメントを見てみると、GetEncoding メソッドの説明に、
コード ページ IDについては、このページに
使用可能なエンコーディングのコード ページ IDは、このページの下の方にある表にまとまっている。
今回は、Shift_JISのCSVを読み込みたいので、932を指定する。
GetEncoding メソッドは、staticメソッドなので、インスタンスを作る必要はなく、下記のようにすれば良い。
これを、下記のように、一度変数に格納してから、-Encodingオプションの引数に指定してもいいし、
直接指定して、ワンライナーで書いてもいい。その場合は、括弧でくくる必要がある。
以上で、無事、PowerShell 6で、Shift_JISのCSVをImport-Csvで読み込むことができた。
下記、Get-Contentの例。
文字コードがshift-jisのファイル、test.csvの中身を出力している。
文字化けせずに、出力できている。
下記、Out-Fileの例。
文字コードがshift-jisのファイル、test.csvを読み込み、文字コードがutf-8のファイル、test2.csvとして出力している。
test2.csvを、-Encodingの指定なし(utf-8)でGet-Contentすると、文字化けせずに出力されることが確認できた。
下記、Export-Csvの例。
Export-Csvの入力はPSObjectなので、まず、PSObjectを作成する。
下記で、上の$objを、文字コードがshift-jisのファイル、test3.csvとして出力している。
> $obj | Export-Csv -Encoding ([System.Text.Encoding]::GetEncoding(932)) -Path test3.csv
shift-jisでImport-Csvすると、文字化けせずに読み込まれることが確認できた。
以上、PowerShell 6で、
について、まとめた。
PowerShell 4で作ったShift_JIS(シフトJIS)のCSVを読み込むスクリプトを、PowerShell 6で動かしたら文字化けした話。
結論としては、下記のようにすればOK。
> Import-Csv -Encoding ([System.Text.Encoding]::GetEncoding(932)) path_to_csv_file
現象
PowerShell 4では、このページにあるように、Import-Csvコマンドレットのオプションとして、-Encoding defaultを付ければよかった。ところが、PowerShell 6では上手くいかない。
例えば、下記のようなshift-jisのCSVがある。
名前,年齢
田中,20
山田,10
これを、-Encoding defaultオプションで読み込むと、
> Import-Csv -Encoding default ./test.csv
O N
---- ----
c 20
Rc 10
このように文字化けする具合だ。
原因
まず、「default」がutf-8に変わったのが原因のようだ。.NET Framework クラスライブラリーの、System.Text名前空間の、Encodingクラスの、Defaultプロパティーを確認した。
> [System.Text.Encoding]::Default
BodyName : utf-8
EncodingName : Unicode (UTF-8)
HeaderName : utf-8
WebName : utf-8
WindowsCodePage : 1200
IsBrowserDisplay : True
IsBrowserSave : True
IsMailNewsDisplay : True
IsMailNewsSave : True
IsSingleByte : False
EncoderFallback : System.Text.EncoderReplacementFallback
DecoderFallback : System.Text.DecoderReplacementFallback
IsReadOnly : True
CodePage : 65001
対処
-Encodingオプションの引数に、shift-jisを指定すればよい。
-Encodingパラメーターは全てSystem.Text.Encoding型に統一されます。とある。ヘルプを見てみると、確かにEncoding型を要求するようだ。
> Get-Help Import-Csv
Import-Csv [[-Path] <string[]>] [[-Delimiter] <char>] [-LiteralPath <string[]>] [-Header <string[]>] [-Encoding <Encoding>] [<CommonParameters>]
Encodingクラスのドキュメントを見てみると、GetEncoding メソッドの説明に、
指定したコード ページ ID に関連付けられたエンコーディングを返します。とあるので、これが使えそうだ。
コード ページ IDについては、このページに
「文字セット」とは正式には「符号化文字集合」と呼ばれ、取り扱う対象となる文字集合を定義して命名と番号付けを行ったものです。例えば「JIS X 208」や「Unicode 4.0」などの名称で定義されています。ソフトウェアベンダーが発行するドキュメントでは「コードページ」と表記されていることが多いです。とあるので、文字セットに付けられた番号、すなわちUTF-8なら65001、Shift_JISなら932の、おなじみの数値だ。
使用可能なエンコーディングのコード ページ IDは、このページの下の方にある表にまとまっている。
今回は、Shift_JISのCSVを読み込みたいので、932を指定する。
GetEncoding メソッドは、staticメソッドなので、インスタンスを作る必要はなく、下記のようにすれば良い。
> [System.Text.Encoding]::GetEncoding(932)
BodyName :
EncodingName : Japanese (Shift-JIS)
HeaderName :
WebName : shift_jis
WindowsCodePage :
IsBrowserDisplay :
IsBrowserSave :
IsMailNewsDisplay :
IsMailNewsSave :
IsSingleByte : False
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 932
これを、下記のように、一度変数に格納してから、-Encodingオプションの引数に指定してもいいし、
> $shiftJis = [System.Text.Encoding]::GetEncoding(932)
> Import-Csv -Encoding $shiftJis ./test.csv
名前 年齢
-- --
田中 20
山田 10
直接指定して、ワンライナーで書いてもいい。その場合は、括弧でくくる必要がある。
> Import-Csv -Encoding ([System.Text.Encoding]::GetEncoding(932)) ./test.csv
名前 年齢
-- --
田中 20
山田 10
以上で、無事、PowerShell 6で、Shift_JISのCSVをImport-Csvで読み込むことができた。
その他のコマンドレットの文字コード指定
Get-Content、Out-File、Export-Csvなども同様に、文字コードを指定するには、-Encodingオプションの引数に、対応する文字コードのSystem.Text.Encodingを指定する。下記、Get-Contentの例。
> Get-Content -Encoding ([System.Text.Encoding]::GetEncoding(932)) ./test.csv
名前,年齢
田中,20
山田,10
文字コードがshift-jisのファイル、test.csvの中身を出力している。
文字化けせずに、出力できている。
下記、Out-Fileの例。
文字コードがshift-jisのファイル、test.csvを読み込み、文字コードがutf-8のファイル、test2.csvとして出力している。
> Get-Content -Encoding ([System.Text.Encoding]::GetEncoding(932)) ./test.csv | Out-File -Encoding ([System.Text.Encoding]::GetEncoding(65001)) -Path test2.csv
test2.csvを、-Encodingの指定なし(utf-8)でGet-Contentすると、文字化けせずに出力されることが確認できた。
> Get-Content ./test2.csv
名前,年齢
田中,20
山田,10
下記、Export-Csvの例。
Export-Csvの入力はPSObjectなので、まず、PSObjectを作成する。
> $obj = New-Object -TypeName PSObject
> $obj | Add-Member -Type NoteProperty -Name "名前" -Value "テスト"
> $obj
名前
--
テスト
> $obj | Export-Csv -Encoding ([System.Text.Encoding]::GetEncoding(932)) -Path test3.csv
shift-jisでImport-Csvすると、文字化けせずに読み込まれることが確認できた。
> Import-Csv -Encoding ([System.Text.Encoding]::GetEncoding(932)) ./test3.csv
名前
--
テスト
以上、PowerShell 6で、
- Shift_JISのCSVファイルを、Import-Csvで文字化けせずに読み込む方法
- Import-Csv、Get-Content、Out-File、Export-Csvコマンドレットで、文字コードを指定する方法
について、まとめた。
コメント
コメントを投稿