about_Character_Encoding

简短说明

介绍 PowerShell 如何对字符串数据的输入和输出使用字符编码。

长说明

Unicode 是一种全球字符编码标准。 系统将 Unicode 专用于字符和字符串操作。 有关 Unicode 的各个方面的详细说明,请参阅 Unicode 标准

Windows 支持 Unicode 和传统字符集。 Windows 代码页等传统字符集使用 8 位值或 8 位值的组合来表示特定语言或地理区域设置中使用的字符。

PowerShell 默认使用 Unicode 字符集。 但是,多个 cmdlet 具有 Encoding 参数,该参数可为不同字符集指定编码。 此参数允许你选择与其他系统和应用程序互操作所需的特定字符编码。

以下 cmdlet 具有 Encoding 参数:

  • Microsoft.PowerShell.Management
    • Add-Content
    • Get-Content
    • Set-Content
  • Microsoft.PowerShell.Utility
    • Export-Clixml
    • Export-Csv
    • Export-PSSession
    • Format-Hex
    • Import-Csv
    • Out-File
    • Select-String
    • Send-MailMessage

字节顺序标记

字节顺序标记 (BOM) 是文件或文本流的前几个字节中的 Unicode 签名,它指示用于数据的 Unicode 编码。 有关详细信息,请参阅字节顺序标记文档。

在 Windows PowerShell 中,除 UTF7 之外的任何 Unicode 编码都是会创建 BOM。 PowerShell(v6 及更高版本)默认对所有文本输出都使用 utf8NoBOM

为了获得最佳的整体兼容性,请避免在 UTF-8 文件中使用 BOM。 Unix 平台和 Windows 平台上使用的 Unix 继承实用程序不支持 BOM。

同样,应避免使用 UTF7 编码。 UTF-7 不是标准的 Unicode 编码,在所有版本的 PowerShell 中都是不带 BOM 编写的。

在类 Unix 平台上创建 PowerShell 脚本或在 Windows 上使用跨平台编辑器(例如 Visual Studio Code)会生成使用 UTF8NoBOM 编码的文件。 这些文件在 PowerShell 中正常工作,但如果文件包含非 Ascii 字符,则可能会在 Windows PowerShell 中不起作用。

如果需要在脚本中使用非 Ascii 字符,请将它们保存为带有 BOM 的 UTF-8 文件。 如果没有 BOM,Windows PowerShell 会将脚本误解为是在旧的“ANSI”代码页中编码的。 相反,具有 UTF-8 BOM 的文件在类 Unix 平台上可能会出现问题。 许多 Unix 工具(如 catsedawk)以及一些编辑器(如 gedit)不知道如何处理 BOM。

Windows PowerShell 中的字符编码

在 PowerShell 5.1 中,Encoding 参数支持以下值:

  • Ascii 使用 Ascii(7 位)字符集。
  • BigEndianUnicode 将 UTF-16 与 big-endian 字节顺序配合使用。
  • BigEndianUTF32 将 UTF-32 与 big-endian 字节顺序配合使用。
  • Byte 将一组字符编码为一个字节序列。
  • Default 使用与系统的活动代码页(通常是 ANSI)对应的编码。
  • Oem 使用与系统的当前 OEM 代码页对应的编码。
  • StringUnicode 相同。
  • Unicode 将 UTF-16 与 little-endian 字节顺序配合使用。
  • UnknownUnicode 相同。
  • UTF32 将 UTF-32 与 little-endian 字节顺序配合使用。
  • UTF7 使用 UTF-7。
  • UTF8 使用 UTF-8(带 BOM)。

一般而言,Windows PowerShell 默认使用 Unicode UTF-16LE 编码。 但是,Windows PowerShell 中 cmdlet 使用的默认编码不一致。

注意

使用除 UTF7 之外的任何 Unicode 编码都是会创建 BOM。

对于将输出写入文件的 cmdlet:

  • Out-File 以及重定向运算符 >>> 会创建 UTF-16LE 文件,这与 Set-ContentAdd-Content 明显不同。

  • New-ModuleManifestExport-CliXml 也会创建 UTF-16LE 文件。

  • 当目标文件为空或不存在时,Set-ContentAdd-Content 使用 Default 编码。 Default 是由活动系统区域设置的 ANSI 旧代码页指定的编码。

  • Export-Csv 会创建 Ascii 文件,但在使用 Append 参数时会使用不同的编码(请参阅下文)。

  • 默认情况下,Export-PSSession 会创建带有 BOM 的 UTF-8 文件。

  • New-Item -Type File -Value 会创建不带 BOM 的 UTF-8 文件。

  • 默认情况下,Send-MailMessage 使用 Ascii 编码。

  • Start-Transcript 会创建带有 BOM 的 Utf8 文件。 使用 Append 参数时,编码可能有所不同(请参阅下文)。

对于追加到现有文件的命令:

  • Out-File -Append>> 重定向运算符不会尝试匹配现有目标文件内容的编码。 除非使用 Encoding 参数,否则它们将使用默认编码。 追加内容时必须使用文件原始编码。

  • 如果没有显式 Encoding 参数,Add-Content 会检测现有编码并自动将其应用到新内容。 如果现有内容没有 BOM,则会使用 Default ANSI 编码。 Add-Content 的行为与 PowerShell(v6 及更高版本)中的行为相同,只是默认编码为 Utf8

  • 当目标文件包含 BOM 时,Export-Csv -Append 与现有编码匹配。 如果没有 BOM,它将使用 Utf8 编码。

  • Start-Transcript -Append 与包含 BOM 的文件的现有编码匹配。 如果没有 BOM,则默认为 Ascii 编码。 当脚本中的数据包含多字节字符时,此编码可能会导致数据丢失或字符损坏。

对于在没有 BOM 的情况下读取字符串数据的 cmdlet:

  • Get-ContentImport-PowerShellDataFile 使用 Default ANSI 编码。 PowerShell 引擎从文件读取源代码时也使用 ANSI。

  • 在没有 BOM 的情况下,Import-CsvImport-CliXmlSelect-String 采用 Utf8

PowerShell 中的字符编码

在 PowerShell(v7.1 及更高版本)中,Encoding 参数支持以下值:

  • ascii:对 ASCII(7 位)字符集使用编码。
  • ansi:对当前区域性的 ANSI 代码页使用编码。 此选项是在 PowerShell 7.4 中添加的。
  • bigendianunicode:使用 big-endian 字节顺序以 UTF-16 格式进行编码。
  • bigendianutf32:使用 big-endian 字节顺序以 UTF-32 格式进行编码。
  • oem:对 MS-DOS 和控制台程序使用默认编码。
  • unicode:使用 little-endian 字节顺序以 UTF-16 格式进行编码。
  • utf7:采用 UTF-7 格式编码。
  • utf8:采用 UTF-8 格式(无 BOM)进行编码。
  • utf8BOM:使用字节顺序标记 (BOM) 以 UTF-8 格式进行编码
  • utf8NoBOM:不使用字节顺序标记 (BOM) 以 UTF-8 格式进行编码
  • utf32:使用 little-endian 字节顺序以 UTF-32 格式进行编码。

PowerShell 默认对所有输出都使用 utf8NoBOM

从 PowerShell 6.2 开始,Encoding 参数还允许注册代码页的数字 ID(如 -Encoding 1251)或已注册代码页的字符串名称(如 -Encoding "windows-1251")。 有关详细信息,请参阅 Encoding.CodePage .NET 文档。

从 PowerShell 7.4 开始,可以使用 Encoding 参数的 Ansi 值来传递当前区域性 ANSI 代码页的数字 ID,而无需手动指定它。

更改默认编码

PowerShell 有两个可用于更改默认编码行为的默认变量。

  • $PSDefaultParameterValues
  • $OutputEncoding

有关详细信息,请参阅 about_Preference_Variables

从 PowerShell 5.1 开始,重定向运算符(>>>)调用 Out-File cmdlet。 因此,可以使用 $PSDefaultParameterValues 首选项变量设置它们的默认编码,如以下示例所示:

$PSDefaultParameterValues['Out-File:Encoding'] = 'utf8'

使用以下语句可更改具有 Encoding 参数的所有 cmdlet 的默认编码。

$PSDefaultParameterValues['*:Encoding'] = 'utf8'

重要

将此命令放入 PowerShell 配置文件中会使首选项成为会话全局设置,该设置会影响未显式指定编码的所有命令和脚本。

同样,应该在你希望行为方式与此相同的脚本或模块中包含这样的命令。 使用这些命令可确保 cmdlet 的行为方式与此相同,即使由其他用户、在不同计算机上或在不同版本的 PowerShell 中运行也是如此。

自动变量 $OutputEncoding 影响 PowerShell 用于与外部程序通信的编码。 它不会影响输出重定向运算符和 PowerShell cmdlet 用于保存到文件的编码。

另请参阅