Isa@Diary

ソフトウェア開発やってます。プログラミングとか、US生活とかについて書きます。

Powershellでcharからstringを作りたかった

あまりにもずっと何も書いていなかったので。
今回はPowershellの話です。

状況

  • ある文字のUnicodeのCodepointか、バイト列が解っている
  • Codepointから文字列を作りたい

方法1

PS C:\> new-object string -ArgumentList 0x6b7b
死

BMPの文字ならこれで大丈夫、それ以外だとうまくいかない。
たとえばみんな大好き𩸽(U+29E3D)

PS C:\> new-object string -ArgumentList 0x29e3d
new-object : "String" の引数 "0" (値 "0x29e3d") を型 "System.Char[]" に変換できません: "値 "0x29e3d" を型 "System.Char[
]" に変換できません。エラー: "値 "171581" を型 "System.Char" に変換できません。エラー: "文字型に対して値が大きすぎるか
、または小さすぎます。"""
発生場所 行:1 文字:1
+ new-object string -ArgumentList 0x29e3d
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [New-Object]、MethodException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

方法2

PS C:\> [char]::ConvertFromUtf32(0x29e3d)
𩸽

Codepoint1つならこれが便利。

方法3

ではか゚やIVSのような複数Codepointで1文字の場合はどうするか。
System.Stringには
String Constructor (Char[]) (System)
というctorがあるのでこれを呼びたい。
たとえばか゚はU+304B U+309Aなので

PS C:\>new-object string -ArgumentList ([char[]](@(0x304b, 0x309a)))
かかかかか…

こうすると
String Constructor (Char, Int32) (System)
こっちのctorが呼ばれてしまう。
キャストを変えたりしてみたもののnew-objectではお目当てのctorは呼べなかった。

結局
Activator.CreateInstance Method (Type, Object[]) (System)
これを使って

PS C:\> [System.Activator]::CreateInstance([System.String], [char[]]@(0x304b, 0x309a))
か゚

とすると作ることができる

まとめ

charからstringを作りたいときの方法は少なくとも3つある

  • new-objectを使う
    • 作りたい文字がBMPのときのみ
  • char.ConvertFromUtf32を使う
    • 1codepointならなんでも
  • Activator.CreateInstanceを使う
    • 合成文字の場合

new-objectを使ってstring(char[])を呼ぶ方法ってないのだろうか。