Linux 和 Windows 之间的文本编码

Text Encoding between Linux and Windows

我的主要问题是如何让 Linux 中的文本文件在 PowerShell 中正确显示。

在Linux中,我有一些带有特殊字符的文本文件,实际上记事本显示的文本文件与在Linux中显示的完全一样:

不幸的是,我的程序打印到我的 Linux 终端,因此我需要在我的 Windows 终端中输出相同的内容。我通过其他答案看到

  1. 我需要使用 TrueType 字体,所以我使用的是 Lucidia Console
  2. 在我的 Linux 设备上,编码是 UTF-8。根据我在网上找到的每个答案,CHCP 65001 将 PowerShell 中的代码页切换为 UTF-8
  3. Windows Powershell 可以更好地显示内容,所以虽然我尝试使用命令提示符,但我现在正在使用 PowerShell。

使用 CHCP 65001 然后键入

more my_file.txt

显示这个:

同时使用

Get-Content -Encoding UTF8 my_file.txt

输出:

这些结果都不够好,但我实际上担心 Get-Content 在这里做了一些不同的事情。我要传输到 windows 的代码是用 Free Pascal 编写的,在 Free Pascal 中,我可以提供 UTF-8 代码页,仅此而已。因此,虽然 Get-Content 对我来说是一个很好的命令来检查 PowerShell 是否能够产生所需的输出,但对我来说使用它并不实际。在 Pascal 中,输出(写入 PowerShell 显示)显示为:

这也很糟糕,这些线应该连接起来,因为它们在 Linux 中连接(显然有些字符被解释为 ?)。但是,这可能是在 Pascal 中选择的代码页的问题,这将是下一步。

我现在的问题是,如何让 Windows Powershell 默认显示一个文本文件,就像记事本版本中显示的那样。 运行 Get-Content 在我的代码中到处都是不切实际的,所以虽然这个结果看起来更有希望,但我不能遵循它。

作为后续问题,因为我无法在网上的任何地方找到它,在显示内容方面这里的主要参与者是什么,因为它显然是一个比编码更大的故事。为什么 'more' 和 'Get-Content' 命令显示不同的输出?为什么'Get-Content'不能看完所有内容?我曾假设 UTF-8 是一个通用标准,可以读取 UTF-8 的程序至少可以实际读取所有字符,但它们的读取方式都不同。

作为文本的输入是:

    ╭─────╮
    │     │
  ╭─│───╮ │
  │ │   │ │
  │ │ ╭─│───╮
  │ │ │ │ │ │
╭─│───│─╯ │ │
│ │ │ │   │ │
│ │ ╰─╯   │ │
│ │       │ │
│ ╰───────│─╯
│         │
╰─────────╯

针对下面发布的回答,我可以看到

more my_file.txt

产生

使用

$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = 
  New-Object System.Text.UTF8Encoding 
  • 确保您的 UTF-8 编码文本文件 具有 BOM - 否则,您的文件将被 Windows PowerShell 误解为基于系统的活动 ANSI 代码页进行编码(而 PowerShell [Core] 6+ 现在值得庆幸的是,在没有物料清单)。

    • 或者,使用 Get-Content -Encoding Utf8 my_file.txt 明确指定文件的编码。

    • 有关 Windows PowerShell 与 PowerShell [Core] 中字符编码的全面讨论,请参阅

  • 来自外部程序的输出被正确捕获在变量 正确重定向到文件 您需要将 [Console]::OutputEncoding 设置为给定程序在输出时使用 的字符编码 (对于仅仅 打印到显示器 这可能不是必需的,但是):

    • 如果代码页 65001 (UTF-8) 有效 并且您的程序支持 ,您需要设置 [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding;请参阅下文了解如何确保 65001 真正生效,因为 运行ning chcp 65001 来自 PowerShell 内部 不是有效。

    • 您提到了 FreePascal,描述了其 Unicode 支持 here
      但是,您的屏幕截图表明您的 FreePascal 程序的输出是 而不是 UTF-8,因为圆角字符被转码为 ? 字符(这表明有损转码到系统的 OEM 代码页,其中不存在这些字符)。

    • 因此,要解决您的问题您必须确保您的 FreePascal 程序 无条件 输出 UTF-8 或 遵循活动代码页(由chcp报告),假设您首先将其设置为65001( UTF-8 代码页;见下文)。

  • 选择可以渲染圆角Unicode字符的字体(如U+256D) in your console window; the Windows PowerShell default font, Lucinda Console, can not (it renders ,如图你的问题),但是 Consolas,例如(PowerShell [Core] 6+ 默认使用),can.


使用 UTF-8 编码与外部程序一致:

注意

  • 下面的命令对于 PowerShell 命令(例如 Get-Content cmdlet)既不是必需的,也没有任何影响。

  • 一些 遗留控制台应用程序 - 特别是 more.com(Windows PowerShell 包装在 more function) - 根本不支持 Unicode,只支持旧的 OEM 代码页。[*]

According to every answer I can find online, CHCP 65001 switches the code page in PowerShell to UTF-8

chcp 65001 如果 运行 从 在 PowerShell[=128 中工作=],因为 .NET 缓存 PowerShell 会话启动时的 [Console]::OutputEncoding 值,以及当时有效的代码页。

相反,您可以使用以下命令完全使控制台 window UTF-8 感知(这也隐含地使 chcp 之后报告 65001):

$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding =
                    New-Object System.Text.UTF8Encoding

这使得 PowerShell 将外部程序的输出解释为 UTF-8,并将它发送 外部程序的数据编码为 UTF-8(感谢首选项变量 $OutputEncoding).

有关详细信息,请参阅


[*] 在 UTF-8 代码页 65001 生效的情况下,more 悄悄跳过包含至少一个无法映射到系统 OEM 代码页的 Unicode 字符(系统的单字节 OEM 代码页中不存在的任何字符,只能表示 256 个字符),在这种情况下适用于包含圆角的行字符,例如 (方框绘图光弧向下和向右,U+256D)。