PowerShell 技能连载 - 获取文本文件编码

文本文件可以以不同的编码存储。需要正确地指定编码,才能正确地读取它们。这是为什么多数读取文本文件的 cmdlet 提供 -Encoding 参数(例如 Get-Content)。如果没有指定正确的编码,您可能会看到一堆乱码。

那么如何(自动地)确认某个指定的文本文件所使用的编码?以下是一个好用的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
function Get-Encoding
{
param
(
[Parameter(Mandatory,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[Alias('FullName')]
[string]
$Path
)

process
{
$bom = New-Object -TypeName System.Byte[](4)

$file = New-Object System.IO.FileStream($Path, 'Open', 'Read')

$null = $file.Read($bom,0,4)
$file.Close()
$file.Dispose()

$enc = [Text.Encoding]::ASCII
if ($bom[0] -eq 0x2b -and $bom[1] -eq 0x2f -and $bom[2] -eq 0x76)
{ $enc = [Text.Encoding]::UTF7 }
if ($bom[0] -eq 0xff -and $bom[1] -eq 0xfe)
{ $enc = [Text.Encoding]::Unicode }
if ($bom[0] -eq 0xfe -and $bom[1] -eq 0xff)
{ $enc = [Text.Encoding]::BigEndianUnicode }
if ($bom[0] -eq 0x00 -and $bom[1] -eq 0x00 -and $bom[2] -eq 0xfe -and $bom[3] -eq 0xff)
{ $enc = [Text.Encoding]::UTF32}
if ($bom[0] -eq 0xef -and $bom[1] -eq 0xbb -and $bom[2] -eq 0xbf)
{ $enc = [Text.Encoding]::UTF8}

[PSCustomObject]@{
Encoding = $enc
Path = $Path
}
}
}

以下是一段检查您用户配置文件中所有文本文件的测试代码:

1
2
3
4
5
6
7
8
9
10
PS> dir $home -Filter *.txt -Recurse | Get-Encoding

Encoding Path
-------- ----
System.Text.UnicodeEncoding C:\Users\tobwe\E006_psconfeu2019.txt
System.Text.UnicodeEncoding C:\Users\tobwe\E009_psconfeu2019.txt
System.Text.UnicodeEncoding C:\Users\tobwe\E027_psconfeu2019.txt
System.Text.ASCIIEncoding C:\Users\tobwe\.nuget\packages\Aspose.Words\18.12.0\...
System.Text.ASCIIEncoding C:\Users\tobwe\.vscode\extensions\ms-vscode.powers...
System.Text.UTF8Encoding C:\Users\tobwe\.vscode\extensions\ms-vscode.powers...
评论