🐶
PowerShellで文字コードを判別したい
ちゃんとやりたければ多分ReadJEnc使うのが正解なんだろーけど
イチイチ小物にDLL突っ込む根性がおっさんにはありませんでしたのよオホホホホ
ってわけでおっさんは太古の記憶を元に以下を引っ張り出してどーにかしました
で、こいつ更に元ネタがあるんだけどこの場合ライセンスってどーなんだろーね???
怖いし一応元ネタの元ネタへのリンクだけでも張っとこーか、クワバラクワバラ
本題
基本的にはBOMで判断しますが駄目ならスコアリングでどーにかします
コメントにも書いてありますがスコアリングのそれっぽさ判別は完全に手抜きで
末尾のややこしい処理なんかはどーせ大して効かないだろってことで普通にオミットしてます
つーわけで駄目なら駄目で大人しくこっち使ってください
(BOMなしだと)UTF-16とかそもそもガン無視だしねー
Function AutoGuessEncodingFileSimple {
param (
[Parameter(Mandatory = $true)] [string] $Path
)
begin {}
process {
return AutoGuessEncodingByteSimple ([System.IO.File]::ReadAllBytes($Path))
}
end {}
}
Function AutoGuessEncodingByteSimple {
param (
[Parameter(Mandatory = $true)] [byte[]] $TextData
)
begin {}
process {
# BOMによるエンコード判定
foreach ($elm in [System.Text.Encoding]::GetEncodings()) {
$oAmb = $elm.GetEncoding().GetPreamble()
if ($oAmb.Length -gt 0 ) {
if (Compare-Object $TxtData[0..($oAmb.Length - 1)] $oAmb -IncludeEqual -ExcludeDifferent) {
return $elm.GetEncoding()
}
}
}
# BOM無しなので日本語前提にSJIS/EUC/UTF8の何れかをソレっぽさで判定する
# 元ネタは特徴的な文字コードを数え上げてスコアリングしてたが...
# ・スコアリングせずソレっぽい位置を数えるように変更
# ・末尾のややこしい処理は移植面倒なのでバッサリ破棄
# 元々の処理が推定だし単発スクリプトならコレで良いでしょ多分
$SJISCount = 0..($TxtData.Length - 2) | Where-Object {
$b1 = $TxtData[$_ + 0]
$b2 = $TxtData[$_ + 1]
((0x81 -le $b1 -and $b1 -le 0x9F) -or (0xE0 -le $b1 -and $b1 -le 0xFC)) -and
((0x40 -le $b2 -and $b2 -le 0x7E) -or (0x80 -le $b2 -and $b2 -le 0xFC))
}
$EUCJCount = 0..($TxtData.Length - 2) | Where-Object {
$b1 = $TxtData[$_ + 0]
$b2 = $TxtData[$_ + 1]
(((0xA1 -le $b1 -and $b1 -le 0xFE) -and (0xA1 -le $b2 -and $b2 -le 0xFE)) -or
((0x8E -eq $b1) -and (0xA1 -le $b2 -and $b2 -le 0xDF)))
}
$UTF8Count = 0..($TxtData.Length - 2) | Where-Object {
$b1 = $TxtData[$_ + 0]
$b2 = $TxtData[$_ + 1]
(0xC0 -le $b1 -and $b1 -le 0xDF) -and (0x80 -le $b2 -and $b2 -le 0xBF)
}
if ($SJISCount.Count -gt $EUCJCount.Count -and $SJISCount.Count -gt $UTF8Count.Count) {
return [System.Text.Encoding]::GetEncoding("Shift-JIS")
} elseif ($EUCJCount.Count -gt $SJISCount.Count -and $EUCJCount.Count -gt $UTF8Count.Count) {
return [System.Text.Encoding]::GetEncoding("EUC-JP")
} else {
return [System.Text.Encoding]::GetEncoding("UTF-8")
}
}
end {}
}
lt/le/gt/geがパット見でわかるやつって相当HTMLで鍛えてんだろーなぁ
K&R版C言語にしか見えないParamと同じでマジでキショいわ
蛇足
でもPowerShell5の闇は深ぇんすわ
実は標準コマンドレットの-Encodingは[System.Text.Encoding]じゃねぇのです
ってわけで例えばCSVとかShift-JISで出力するならこーんな感じで文字列指定が必要です
PowerShell7でも互換性のためか文字列指定可能なんで古い方に合わせるしかッ
Export-Csv -Path $Path -Encoding "OEM"
Discussion