Out-File似乎在使用UTF-8时强制BOM:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
我怎么能写一个文件在UTF-8没有BOM使用PowerShell?
更新2021
自从10年前我写这个问题以来,PowerShell已经发生了一些变化。检查下面的多个答案,它们有很多有用的信息!
Out-File似乎在使用UTF-8时强制BOM:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
我怎么能写一个文件在UTF-8没有BOM使用PowerShell?
更新2021
自从10年前我写这个问题以来,PowerShell已经发生了一些变化。检查下面的多个答案,它们有很多有用的信息!
当前回答
使用该方法编辑UTF8-NoBOM文件,生成编码正确的文件-
$fileD = "file.xml"
(Get-Content $fileD) | ForEach-Object { $_ -replace 'replace text',"new text" } | out-file "file.xml" -encoding ASCII
起初我对这种方法持怀疑态度,但它让我感到惊讶,而且很有效!
使用powershell 5.1版进行测试
其他回答
[System.IO.FileInfo] $file = Get-Item -Path $FilePath
$sequenceBOM = New-Object System.Byte[] 3
$reader = $file.OpenRead()
$bytesRead = $reader.Read($sequenceBOM, 0, 3)
$reader.Dispose()
#A UTF-8+BOM string will start with the three following bytes. Hex: 0xEF0xBB0xBF, Decimal: 239 187 191
if ($bytesRead -eq 3 -and $sequenceBOM[0] -eq 239 -and $sequenceBOM[1] -eq 187 -and $sequenceBOM[2] -eq 191)
{
$utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
[System.IO.File]::WriteAllLines($FilePath, (Get-Content $FilePath), $utf8NoBomEncoding)
Write-Host "Remove UTF-8 BOM successfully"
}
Else
{
Write-Warning "Not UTF-8 BOM file"
}
如何使用PowerShell从文件中删除UTF8字节顺序标记(BOM)
从版本6开始,powershell支持UTF8NoBOM编码用于设置内容和输出文件,甚至将其用作默认编码。
所以在上面的例子中,它应该是这样的:
$MyFile | Out-File -Encoding UTF8NoBOM $MyPath
使用.NET的UTF8Encoding类并将$False传递给构造函数似乎是可行的:
$MyRawString = Get-Content -Raw $MyPath
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
[System.IO.File]::WriteAllLines($MyPath, $MyRawString, $Utf8NoBomEncoding)
这个脚本将把DIRECTORY1中的所有.txt文件转换为不含BOM的UTF-8格式,并将它们输出到DIRECTORY2
foreach ($i in ls -name DIRECTORY1\*.txt)
{
$file_content = Get-Content "DIRECTORY1\$i";
[System.IO.File]::WriteAllLines("DIRECTORY2\$i", $file_content);
}
如果你想使用[System.IO.File]::WriteAllLines(),你应该将第二个参数转换为String[](如果$MyFile的类型是Object[]),并指定绝对路径$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath),如:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Set-Variable MyFile
[System.IO.File]::WriteAllLines($ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath), [String[]]$MyFile, $Utf8NoBomEncoding)
如果你想使用[System.IO.File]::WriteAllText(),有时你应该将第二个参数管道到| Out-String |中,以显式地将crlf添加到每行的末尾(特别是当你使用ConvertTo-Csv时):
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Out-String | Set-Variable tmp
[System.IO.File]::WriteAllText("/absolute/path/to/foobar.csv", $tmp, $Utf8NoBomEncoding)
或者你可以使用[Text.Encoding]::UTF8.GetBytes()与Set-Content -Encoding Byte:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding $False
Get-ChildItem | ConvertTo-Csv | Out-String | % { [Text.Encoding]::UTF8.GetBytes($_) } | Set-Content -Encoding Byte -Path "/absolute/path/to/foobar.csv"
参见:如何将ConvertTo-Csv的结果写入没有BOM的UTF-8文件