ファイルの文字コード判定

指定ファイルの文字コードを判定するために、.NET Frameworkのクラスを使用したPowerShellスクリプトを作成します。このスクリプトでは、System.Text.EncodingクラスとSystem.IO.StreamReaderクラスを使用してファイルの文字コードを判定します。

以下はそのスクリプトの例です:

Function Get-FileEncoding {
    param (
        [string]$filePath
    )

    # サポートするエンコーディング
    $encodings = [System.Text.Encoding]::GetEncodings() | ForEach-Object { $_.GetEncoding() }

    # ファイルをバイト配列として読み込み
    $fileBytes = [System.IO.File]::ReadAllBytes($filePath)

    # 文字コード判定
    foreach ($encoding in $encodings) {
        $preAmble = $encoding.GetPreamble()

        # プレアンブルが存在し、ファイルの先頭が一致する場合
        if ($preAmble.Length -gt 0 -and $fileBytes[0..($preAmble.Length - 1)] -eq $preAmble) {
            return $encoding.EncodingName
        }

        # 一致しない場合、デフォルトデコーダでチェック
        try {
            $text = $encoding.GetString($fileBytes)
            [void][System.Text.Encoding]::Convert($encoding, [System.Text.Encoding]::UTF8, $encoding.GetBytes($text))
            return $encoding.EncodingName
        } catch {
            continue
        }
    }

    return "Encoding not detected"
}

# 使用例
$filePath = "path/to/your/file.txt"
$encoding = Get-FileEncoding -filePath $filePath
Write-Output "The encoding of the file is: $encoding"

このスクリプトは以下の手順で動作します:

  1. System.Text.Encodingクラスを使って、サポートされているすべてのエンコーディングを取得します。
  2. 指定されたファイルをバイト配列として読み込みます。
  3. 各エンコーディングについて、プレアンブルをチェックし、ファイルの先頭がそのプレアンブルと一致するか確認します。
  4. プレアンブルが一致しない場合は、デフォルトのデコーダを使ってファイルを読み取り、再度エンコーディングを判定します。
  5. 最初に一致したエンコーディングを返します。

この方法でファイルの文字コードを判定することができます。

バイナリファイルの判定を追加

バイナリファイルの判定を .NET Framework のクラスで行うように修正します。ここでは、System.IO 名前空間のクラスを使ってファイルを読み込み、制御文字をチェックすることでバイナリファイルを判定します。

以下はそのスクリプトです:

Function Get-FileEncodingAndType {
    param (
        [string]$filePath
    )

    # バイナリファイルの判定
    Function Is-BinaryFile {
        param (
            [string]$filePath
        )

        $bytesToRead = 512
        $fileStream = [System.IO.File]::OpenRead($filePath)
        $buffer = New-Object byte[] $bytesToRead
        $fileStream.Read($buffer, 0, $bytesToRead) > $null
        $fileStream.Close()

        foreach ($byte in $buffer) {
            if ($byte -lt 32 -and $byte -ne 9 -and $byte -ne 10 -and $byte -ne 13) {
                return $true
            }
        }
        return $false
    }

    # ファイルがバイナリファイルかどうかを判定
    if (Is-BinaryFile -filePath $filePath) {
        return "The file is a binary file."
    }

    # サポートするエンコーディング
    $encodings = [System.Text.Encoding]::GetEncodings() | ForEach-Object { $_.GetEncoding() }

    # ファイルをバイト配列として読み込み
    $fileBytes = [System.IO.File]::ReadAllBytes($filePath)

    # 文字コード判定
    foreach ($encoding in $encodings) {
        $preAmble = $encoding.GetPreamble()

        # プレアンブルが存在し、ファイルの先頭が一致する場合
        if ($preAmble.Length -gt 0 -and $fileBytes[0..($preAmble.Length - 1)] -eq $preAmble) {
            return $encoding.EncodingName
        }

        # 一致しない場合、デフォルトデコーダでチェック
        try {
            $text = $encoding.GetString($fileBytes)
            [void][System.Text.Encoding]::Convert($encoding, [System.Text.Encoding]::UTF8, $encoding.GetBytes($text))
            return $encoding.EncodingName
        } catch {
            continue
        }
    }

    return "Encoding not detected"
}

# 使用例
$filePath = "path/to/your/file.txt"
$result = Get-FileEncodingAndType -filePath $filePath
Write-Output $result

このスクリプトでは、Is-BinaryFile 関数内で System.IO.File クラスを使用してファイルを開き、最初の512バイトを読み取ります。その後、バイト配列をチェックして制御文字が含まれているかどうかを判定します。制御文字が含まれていればバイナリファイルと見なします。次に、バイナリファイルでない場合にのみ文字コードの判定を行います。