PowerShellと.NET Frameworkを使用して、ファイルの文字コードを高精度に判別する関数を作成しました。UTF-8、Shift_JIS、EUC-JPに対応しています。
function Get-FileEncoding {
param(
[Parameter(Mandatory=$true)]
[string]$Path
)
# ファイルが存在するかチェック
if (-not (Test-Path $Path)) {
throw "ファイルが見つかりません: $Path"
}
# ファイルサイズが0の場合
if ((Get-Item $Path).Length -eq 0) {
return "空のファイルです"
}
# ファイルをバイナリモードで開く
$bytes = [System.IO.File]::ReadAllBytes($Path)
# バイナリファイルかテキストファイルかを判別
function IsBinaryFile($bytes) {
# バイト配列のうち、制御文字以外の割合を計算
$nonTextChars = $bytes | Where-Object { $_ -lt 0x07 -or ($_ -gt 0x0D -and $_ -lt 0x20) }
$nonTextRatio = $nonTextChars.Count / $bytes.Length
# 非テキスト文字が30%以上ならバイナリファイルとみなす
return $nonTextRatio -gt 0.3
}
if (IsBinaryFile $bytes) {
return "バイナリファイルです"
}
# BOMのチェック
$bomEncodings = @{
([byte[]](0x00,0x00,0xFE,0xFF)) = "UTF-32 BE";
([byte[]](0xFF,0xFE,0x00,0x00)) = "UTF-32 LE";
([byte[]](0xFE,0xFF)) = "UTF-16 BE";
([byte[]](0xFF,0xFE)) = "UTF-16 LE";
([byte[]](0xEF,0xBB,0xBF)) = "UTF-8 with BOM";
}
foreach ($bom in $bomEncodings.Keys) {
$bomLength = $bom.Length
if ($bytes.Length -ge $bomLength) {
$fileBom = $bytes[0..($bomLength - 1)]
if ($fileBom -eq $bom) {
return $bomEncodings[$bom]
}
}
}
# サポートするエンコーディングのリスト
$encodings = @(
[System.Text.Encoding]::UTF8,
[System.Text.Encoding]::GetEncoding("Shift_JIS"),
[System.Text.Encoding]::GetEncoding("EUC-JP"),
[System.Text.Encoding]::Unicode, # UTF-16 LE
[System.Text.Encoding]::BigEndianUnicode, # UTF-16 BE
[System.Text.Encoding]::UTF32
)
# エンコーディングを試行
foreach ($encoding in $encodings) {
$decoder = [System.Text.Encoding]($encoding.Clone())
$decoder.DecoderFallback = New-Object System.Text.DecoderExceptionFallback
try {
[void]$decoder.GetString($bytes)
return $encoding.EncodingName
} catch {
# 次のエンコーディングを試す
}
}
return "エンコーディングを判別できませんでした"
}
$encoding = Get-FileEncoding -Path "ファイルのパス.txt"
Write-Host "ファイルのエンコーディングは: $encoding"