PowerShell 5.1 如何輸出 不帶BOM的 UTF-8 檔案
說明是對於 PowerShell 5.1 版本,從6版本以上預設 Out-File 預設就是不帶 BOM的。
解決方案 使用 C# 函式
在 ps 5.1 中唯一解法只有呼叫 C# 的函式,這裡有兩個可以用
[IO.File]::WriteAllText("TestFile.txt", "ㄅㄆㄇㄈ`r`n")
另一個是 Lines 區別只是這個會自動換行
[IO.File]::WriteAllLines("TestFile.txt", "ㄅㄆㄇㄈ")
如果要顯式指定編碼的話是這樣設置
$encoding = New-Object System.Text.UTF8Encoding $False
[IO.File]::WriteAllLines("TestFile.txt", "ㄅㄆㄇㄈ", $encoding)
還有另一個 IO.StreamWriter 的流處理函式,不過那寫起來會比較多行有需要自行參考這篇。
https://github.com/hunandy14/cvEncode/blob/master/cvEncoding.ps1#L160
解決方案 使用第三方函式
自己寫的處理函式,主要用於大量轉檔的。
irm bit.ly/cvEncoding|iex
"ㄅㄆㄇㄈ"| WriteContent "README.md" UTF8
有做過效能測試,使用管道行寫入的總時間約略快於用 WriteAllText 一次寫入整份檔案。這結果是蠻奇怪沒繼續深究,但總之速度是可接受的。
https://github.com/hunandy14/cvEncode/tree/master
------------------------以下舊文------------------------
解決方案1 - ASCII
簡單粗暴的的方法,直接寫入 ASCII 就好了。
不能寫中文,但可以記下來應急的時候很好用。
$FileContent = "only english content"
$dstPath = [Environment]::GetFolderPath("Desktop")
$FileContent | Out-File -Encoding ASCII "$dstPath\utf8.txt"
解決方案2 - WriteAllLines
這個方法就不會出問題了,不過是從記憶體一次寫入大小有限。
$FileContent = "中文UTF8內容"
$dstPath = [Environment]::GetFolderPath("Desktop")
$Enc = (New-Object System.Text.UTF8Encoding $False)
[System.IO.File]::WriteAllLines("$dstPath\utf8.txt", $FileContent, $Enc);
解決方案3 - Out-FileUtf8NoBom
這個函式比較能從根本解決問題
載入很簡單,直接打這行就可以把方法載入了
irm https://gist.github.com/mklement0/8689b9b5123a9ba11df7214f82a673be/raw/Out-FileUtf8NoBom.ps1 | iex
再來使用方法和原本的 Out-File 差不多 (不過原作者並沒有實現全部的接口)
$FileContent = "中文UTF8內容"
$dstPath = [Environment]::GetFolderPath("Desktop")
$FileContent | Out-FileUtf8NoBom $dstPath\utf8.txt
這樣就能簡單生成一個不帶BOM的UTF8文件了。
原作者:https://gist.github.com/mklement0/8689b9b5123a9ba11df7214f82a673be
如何安裝 Out-FileUtf8NoBom 到電腦上
上面的指令關掉之後副程式就沒了,每次都要重新載入,如果想要用久的安裝到電腦上,可以使用下面指令。
Set-ExecutionPolicy RemoteSigned -scope CurrentUser
if (!(Test-Path -Path $PROFILE )) { New-Item -Type File -Path $PROFILE -Force }
irm https://gist.github.com/mklement0/8689b9b5123a9ba11df7214f82a673be/raw/Out-FileUtf8NoBom.ps1 | iex
"`nfunction Out-FileUtf8NoBom {`n${function:Out-FileUtf8NoBom}`n}" | Out-FileUtf8NoBom -Append $PROFILE
這樣就永久安裝到電腦了,隨時都可以用 Out-FileUtf8NoBom 函式了
其他編碼轉換
其他編碼的轉法可以參考這裡的查詢方法
[Text.Encoding]::Default
[Text.Encoding]::UTF8
[Text.Encoding]::GetEncoding('UTF-8')
[Text.Encoding]::GetEncoding('BIG5')
[Text.Encoding]::GetEncoding('Shift_JIS')
[Text.Encoding]::GetEncoding(65001)
[Text.Encoding]::GetEncoding(950)
[Text.Encoding]::GetEncoding(932)
實際使用時像這樣
$Enc_Default = [Text.Encoding]::Default
$Enc_UTF8_BOM = [Text.Encoding]::GetEncoding(65001)
$Enc_UTF8 = New-Object System.Text.UTF8Encoding $False
$Enc_BIG5 = [Text.Encoding]::GetEncoding(950)
$Enc_SIFT = [Text.Encoding]::GetEncoding(932)
$Encoding = $Enc_UTF8
[System.IO.File]::ReadAllLines($Path, $Content, $Encoding);
[System.IO.File]::WriteAllLines($Path, $Content, $Encoding);
UTF8 比較特別要用別的寫法否則會變成帶有BOM的檔案,或者是直接在WriteAllLines() 函數上省略最後面的 $Encoding 參數也可以。
參考