gpt4 book ai didi

powershell - 如何在没有BOM的情况下在PowerShell中重定向输入?

转载 作者:行者123 更新时间:2023-12-03 20:56:47 25 4
gpt4 key购买 nike

我正在尝试通过以下方式重定向PowerShell中的输入:

Get-Content input.txt | my-program args

问题是管道的UTF-8文本前面带有BOM(0xEFBBBF),而我的程序无法正确处理。

一个最小的工作示例:
// File: Hex.java
import java.io.IOException;

public class Hex {
public static void main(String[] dummy) {
int ch;
try {
while ((ch = System.in.read()) != -1) {
System.out.print(String.format("%02X ", ch));
}
} catch (IOException e) {
}
}
}

然后在PowerShell中:
javac Hex.java
Set-Content textfile "ABC" -Encoding Ascii
# Now the content of textfile is 0x41 42 43 0D 0A
Get-Content textfile | java Hex

或者简单地
javac Hex.java
Write-Output "ABC" | java Hex

无论哪种情况,输出都是 EF BB BF 41 42 43 0D 0A

如何在没有0xEFBBBF的情况下将文本通过管道传递到程序中?

最佳答案

注意:
以下内容包含常规信息,这些信息在正常运行的PowerShell环境中将说明OP的症状。该解决方案在OP的情况下不起作用的原因是,目前尚不知道特定于机器的原因。
这个答案是关于将没有BOM的UTF-8发送到外部程序的。如果要使PowerShell控制台窗口在所有方面都使用UTF-8,请参阅this answer

为了确保您的Java程序在没有BOM的情况下接收UTF-8编码的输入,必须将$OutputEncoding设置为不发出BOM的 System.Text.UTF8Encoding 实例:

# Assigns UTF-8 encoding *without a BOM*.
# PowerShell uses this encoding to encode data piped to external programs.
# $OutputEncoding defaults to ASCII(!) in Windows PowerShell, and more sensibly
# to BOM-*less* UTF-8 in PowerShell [Core] v6+
$OutputEncoding = [Text.UTF8Encoding]::new($false)
警告:
  • 不要使用看似等效的New-Object Text.Utf8Encoding $false ,因为由于this GitHub issue中描述的错误,如果您在非全局范围内(例如在脚本中)分配给$OutpuEncoding,则它将无法正常工作。
  • Windows 10 1903及更高版本允许您将无BOM的UTF-8设置为系统范围内的默认编码(尽管请注意,该功能自1909版起仍归为beta)-请参见this answer;开启此功能后的,上述技术无效,这是由于.NET Core的一个错误假设导致始终忽略UTF-8 BOM,无论您将$OutputEncoding设置为哪种编码(该错误可能与this GitHub issue); 唯一的解决方案是关闭功能,如imgx64's answer所示。

  • 相比之下,如果您使用 [Text.Encoding]::Utf8( System.Text.Encoding.UTF8 ),则会获得BOM表-我怀疑您的情况是这样。

    请注意,此问题与 Get-Content读取的任何文件的源编码无关,因为 通过PowerShell管道发送的内容永远不是原始字节流,而是.NET对象,在Get-Content的情况下,意味着.NET字符串发送给( System.String ,内部是一系列UTF-16代码单元)。
    因为要传递到外部程序(在您的情况下为Java应用程序),所以PowerShell会根据preference variable $OutputEncoding 对发送给它的(按需字符串化)对象进行字符编码,结果编码就是外部程序收到。
    也许令人惊讶,即使BOM通常仅在文件中使用,PowerShell也在管道中遵守分配给$OutputEncoding的编码的BOM设置,将其放在发送的第一行(仅)之前。
    请参阅 this answer的底部,以获取有关PowerShell如何处理外部程序的管道输入和输出的更多信息,包括PowerShell解释从外部程序接收的数据时 的影响。

    为了说明使用示例程序的区别(请注意如何使用PowerShell字符串文字作为输入就足够了;无需从文件中读取):
    # Note the EF BB BF sequence representing the UTF-8 BOM.
    # Enclosure in & { ... } ensures that a local, temporary copy of $OutputEncoding
    # is used.
    PS> & { $OutputEncoding = [Text.Encoding]::Utf8; 'hö' | java Hex }
    EF BB BF 68 C3 B6 0D 0A

    # Note the absence of EF BB BF, due to using a BOM-less
    # UTF-8 encoding.
    PS> & { $OutputEncoding = [Text.Utf8Encoding]::new($false); 'hö' | java Hex }
    68 C3 B6 0D 0A
    在Windows PowerShell中,[Console]::OutputEncoding默认为ASCII(!),您将看到以下内容以及默认位置:
    # The default of ASCII(!) results in *lossy* encoding in Windows PowerShell.
    PS> 'hö' | java Hex
    68 3F 0D 0A
    请注意,$OutputEncoding代表文字3F字符,这也是非ASCII ?字符也被音译的原因,因为它没有用ASCII表示;换句话说:信息丢失了。
    现在,PowerShell [Core] v6 +明智地默认为无BOM的UTF-8,因此该默认行为符合预期。
    尽管无BOM的UTF-8是PowerShell [Core]的一致默认值,但对于读取和写入文件的cmdlet,Windows上的ö仍默认从v7.0起默认反射(reflect) Activity 的OEM代码页,以便正确捕获发出UTF-8的外部程序的输出,还必须将其设置为[Console]::OutputEncoding -请参见this GitHub issue

    关于powershell - 如何在没有BOM的情况下在PowerShell中重定向输入?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60124466/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com