我在 git bash 中使用一個腳本,它對期望和生成 protobuf 的 HTTP 端點執行很少的 curl 呼叫。
curl 輸出通過管道傳輸到自定義 proto2json.exe 檔案,最后將結果保存到 JSON 檔案:
#!/bin/bash
SCRIPT_DIR=$(dirname $0)
JSON2PROTO="$SCRIPT_DIR/json2proto.exe"
PROTO2JSON="$SCRIPT_DIR/proto2json.exe"
echo '{"key1":"value1","version":3}' | $JSON2PROTO -v 3 > request.dat
curl --insecure --data-binary @request.dat --output - https://localhost/protobuf | $PROTO2JSON -v 3 > response.json
該腳本運行良好,現在我正在嘗試將其移植到 Powershell:
$SCRIPT_DIR = Split-Path -parent $PSCommandPath
$JSON2PROTO = "$SCRIPT_DIR/json2proto.exe"
$PROTO2JSON = "$SCRIPT_DIR/proto2json.exe"
@{
key1 = value1;
version = 3;
} | ConvertTo-Json | &$JSON2PROTO -v 3 > request.dat
不幸的是,當我比較“git bash”和 Powershell 中生成的二進制檔案時,我看到后一個檔案輸入了額外的零位元組。
這是我真實案例比較的截圖,這里發生了什么?

uj5u.com熱心網友回復:
看起來你最終是在這個之后:
$SCRIPT_DIR = Split-Path -parent $PSCommandPath
$JSON2PROTO = "$SCRIPT_DIR/json2proto.exe"
$PROTO2JSON = "$SCRIPT_DIR/proto2json.exe"
# Make sure that the output from your $JSON2PROTO executable is correctly decoded
# as UTF-8.
# You may want to restore the original encoding later.
[Console]::OutputEncoding = [System.Text.Utf8Encoding]::new()
# Capture the output lines from calling the $JSON2PROTO executable.
# Note: PowerShell captures a *single* output line as-is, and
# *multiple* ones *as an array*.
[array] $output =
@{
key1 = value1;
version = 3;
} | ConvertTo-Json | & $JSON2PROTO -v 3
# Filter out empty lines to extract the one line of interest.
[string] $singleOutputLineOfInterest = $output -ne ''
# Write a BOM-less UTF-8 file with the given text as-is,
# without appending a newline.
[System.IO.File]::WriteAllText(
"$PWD/request.dat",
$singleOutputLineOfInterest
)
至于你嘗試了什么:
在 PowerShell 中,
>是Out-Filecmdlet 的有效別名,其在 Windows PowerShell 中的默認輸出字符編碼是“Unicode”(UTF-16LE) - 這就是您所看到的 - 并且在 PowerShell (Core) 7 中,是無 BOM 的 UTF8。要控制字符編碼,請呼叫Out-File或,對于文本輸入,Set-Content使用-Encoding引數。請注意,您可能還必須確保首先正確解碼外部程式的輸出,這取決于存盤在其中的編碼
[Console]::OutputEncoding- 有關更多資訊,請參閱此答案。請注意,從 v7.2.4 開始,您無法避免在 PowerShell 中執行這些解碼 重新編碼步驟,因為PowerShell 管道目前不能用作原始位元組的管道,如本答案中所討論的,它還鏈接到您的 GitHub 問題提到。
最后,請注意,默認情況下都會
Out-File在輸出檔案中Set-Content附加一個尾隨的平臺原生換行符。雖然-NoNewLine抑制了這一點,但它也抑制了多個輸入物件之間的換行符,因此您可能必須使用-join運算子手動將輸入與所需格式的換行符連接起來,例如(1, 2) -join "`n" | Set-Content -NoNewLine out.txt
如果在 Windows PowerShell 中,您想要創建沒有 BOM 的UTF-8 檔案,則不能使用檔案寫入cmdlet ,而必須直接使用.NET API(相比之下,PowerShell (Core) 7 會生成 BOM-默認情況下更少的 UTF-8 檔案,始終如一)。默認情況下,.NET API 確實并且總是創建無 BOM 的 UTF-8 檔案;例如:
[System.IO.File]::WriteAllLines()將陣列的元素作為行寫入輸出檔案,每行以平臺原生換行符結束,即 Windows 上的 CRLF ( ) 和類 Unix 平臺上的0xD0xALF ( )。0xA[System.IO.File]::WriteAllText()將單個(可能是多行)字串按原樣寫入輸出檔案。重要提示:始終將完整路徑傳遞給與檔案相關的 .NET API,因為 PowerShell 的當前位置(目錄)通常與 .NET 不同。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/478632.html
