Powershell 7.xの場合
以下をResolve-FileEncoding.ps1というファイル名で作成します。(ファイル名はお好みでどうぞ)BOM付UTF-8でファイル作成するとPowerShell 5.1xでもPowerShell 7.xでも動作します。
ソースプログラム
param (
[Parameter(Mandatory = $true)]
[string]$Path
)
function Test-Encoding {
param (
[byte[]]$bytes,
[string]$encodingName
)
try {
$enc = [System.Text.Encoding]::GetEncoding($encodingName)
$utf8 = [System.Text.Encoding]::UTF8
#バイト配列をエンコードに合わせてテキスト化
$text = $enc.GetString($bytes)
# 不正文字(U+FFFD, サロゲートペア)を含むか
# Shift_JISとEUCには存在しない文字である
if ($text -match '[\uFFFD\uD800-\uDFFF]') {
return $false
}
# バイト配列に戻す(往復変換で一致するか)
$reencoded = $enc.GetBytes($utf8.GetString($utf8.GetBytes($text)))
# バイト配列の比較結果を true/falseで返却
return [System.Linq.Enumerable]::SequenceEqual($reencoded, $bytes)
} catch {
return $false
}
}
function Resolve-FileEncoding {
param (
[string]$Path
)
if (-not (Test-Path $Path)) {
Write-Output "File not found: $Path"
return
}
try {
$maxBytes = 4096 # 4KBだけ読む
# 読み取り専用で開く
$fs = [System.IO.File]::OpenRead($Path)
# バイト配列作成
$bytes = New-Object byte[] $maxBytes
# 配列にファイルを読み込み
$readCount = $fs.Read($bytes, 0, $maxBytes)
$fs.Close()
# 実際に読めたサイズに合わせて切り詰め(4Kに満たないファイルを想定)
# 切り詰めというより新たにエリアを確保してコピー
$bytes = $bytes[0..($readCount - 1)]
} catch {
Write-Output "Failed to read file: $_"
return
}
# BOMチェック
if ($bytes.Length -ge 3 -and $bytes[0] -eq 0xEF -and $bytes[1] -eq 0xBB -and $bytes[2] -eq 0xBF) {
# BOM:EF BB BF (UTF-8 with BOM)
Write-Output "UTF-8 with BOM"
return
}
elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFF -and $bytes[1] -eq 0xFE) {
# BOM:FF FE (UTF-16 LE Little Endian)
Write-Output "UTF-16 LE"
return
}
elseif ($bytes.Length -ge 2 -and $bytes[0] -eq 0xFE -and $bytes[1] -eq 0xFF) {
# BOM:FE FF (UTF-16 BE Big Endian)
Write-Output "UTF-16 BE"
return
}
# UTF-8 BOMなし判定(strict)
$utf8Strict = [System.Text.UTF8Encoding]::new($false, $true)
try {
$utf8Strict.GetString($bytes) | Out-Null
Write-Output "UTF-8 (no BOM)"
return
} catch {}
# Shift_JIS 判定
if (Test-Encoding $bytes "shift_jis") {
Write-Output "Shift_JIS"
return
}
# EUC-JP 判定
if (Test-Encoding $bytes "euc-jp") {
Write-Output "EUC-JP"
return
}
Write-Output "Unknown encoding"
}
# --- 関数呼び出し ---
Resolve-FileEncoding -Path $Path