Out-File
在使用 UTF-8 时似乎会强制添加BOM:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
如何使用PowerShell以UTF-8无BOM格式编写文件?
2021年更新
自我10年前提出此问题以来,PowerShell有了一些变化。请检查下面的多个答案,它们包含很多有用的信息!
Out-File
在使用 UTF-8 时似乎会强制添加BOM:
$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "UTF8" $MyPath
如何使用PowerShell以UTF-8无BOM格式编写文件?
自我10年前提出此问题以来,PowerShell有了一些变化。请检查下面的多个答案,它们包含很多有用的信息!
我会建议只使用 Set-Content 命令,不需要其他的。
我的系统中使用的 Power shell 版本是:
PS C:\Users\XXXXX> $PSVersionTable.PSVersion | fl
Major : 5
Minor : 1
Build : 19041
Revision : 1682
MajorRevision : 0
MinorRevision : 1682
PS C:\Users\XXXXX>
所以你需要像下面这样的东西。
PS C:\Users\XXXXX> Get-Content .\Downloads\finddate.txt
Thursday, June 23, 2022 5:57:59 PM
PS C:\Users\XXXXX> Get-Content .\Downloads\finddate.txt | Set-Content .\Downloads\anotherfile.txt
PS C:\Users\XXXXX> Get-Content .\Downloads\anotherfile.txt
Thursday, June 23, 2022 5:57:59 PM
PS C:\Users\XXXXX>
现在,根据屏幕截图检查文件时,它是utf8格式。anotherfile.txt
附言:回答评论中的外部字符问题。使用以下命令将具有外国字符的文件“testfgnchar.txt”的内容复制到“findfnchar2.txt”。
PS C:\Users\XXXXX> Get-Content .\testfgnchar.txt | Set-Content findfnchar2.txt
PS C:\Users\XXXXX>
截图在这里。
注意:目前已经有比我在回答中使用的版本更新的PowerShell存在。
set-content -encoding utf8
可以解决这个问题。 - Chortos-2echo āčķʃλшא⁴ℝ→⅛≈あ子 | set-content file.txt
,您会发现没有一个字符被保留。其他答案的评论中也指出了其他PowerShell命令的同样问题。知道 set-content
默认使用单字节编码的拉丁文当然很好,但它与最初请求的UTF-8非常不同。 - Chortos-2get-content
同样使用 ANSI 编码,就像你在测试中确认看到的那样。如果屏幕截图显示了 get-content a.txt | set-content b.txt
的结果,则它仅将文件读取为 Windows-1252 并将其写回为 Windows-1252,从而产生了逐字节复制。 UTF-8 在整个过程中没有涉及。提出这个问题的根本原因是编码取决于 Windows 设置,因此需要一种可靠的方法来使用 UTF-8。 - Chortos-2将具有相同扩展名的多个文件转换为UTF-8无BOM格式:
$Utf8NoBomEncoding = New-Object System.Text.UTF8Encoding($False)
foreach($i in ls -recurse -filter "*.java") {
$MyFile = Get-Content $i.fullname
[System.IO.File]::WriteAllLines($i.fullname, $MyFile, $Utf8NoBomEncoding)
}
我使用的一种技术是使用Out-File cmdlet将输出重定向到ASCII文件。
例如,我经常运行创建另一个要在Oracle中执行的SQL脚本的SQL脚本。通过简单的重定向(">"),输出将以UTF-16格式显示,而这种格式不被SQLPlus识别。为了解决这个问题:
sqlplus -s / as sysdba "@create_sql_script.sql" |
Out-File -FilePath new_script.sql -Encoding ASCII -Force
sqlplus / as sysdba "@new_script.sql" |
tee new_script.log
更新:正如其他人指出的那样,这将删除非ASCII字符。由于用户要求一种“强制”转换的方法,我假设他们不关心这一点,因为他们的数据可能不包含这样的数据。
如果您关心保留非ASCII字符,那么这不是您的答案。
-Encoding ASCII
可以避免 BOM 问题,但显然你只能得到对 7 位 ASCII 字符 的支持。鉴于 ASCII 是 UTF-8 的子集,因此生成的文件在技术上也是有效的 UTF-8 文件,但 _输入中的所有非 ASCII 字符都将被转换为字面值 ?
字符。 - mklement0$fileD = "file.xml"
(Get-Content $fileD) | ForEach-Object { $_ -replace 'replace text',"new text" } | out-file "file.xml" -encoding ASCII
一开始我对这种方法持怀疑态度,但它让我惊喜并且奏效了!
已在PowerShell版本5.1上进行测试。
$PSDefaultParameterValues['*:Encoding'] = 'utf8'
$filecontent | Out-File $Filename -Encoding default
。请注意,这将重新编码文件为utf8,因此未正确编码的文件将发生变化。 - undefined [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"
}
[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 |
中,以显式地在每行末尾添加 CRLFs(特别是在与 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"
$ExecutionContext.SessionState.Path.GetUnresolvedProviderPathFromPSPath($MyPath)
的更简单的替代方法是 Convert-Path $MyPath
;如果您想确保有一个结尾的 CRLF,请使用 [System.IO.File]::WriteAllLines()
即使只有一个输入字符串(不需要 Out-String
)。 - mklement0$file = get-content -path "C:\temp\myfile.txt" -Encoding UTF8
# do some stuff.
$file[0] | out-file "C:\temp\mynewfile.txt" -Encoding ascii
$file | select -skip 1 | out-file "C:\temp\mynewfile.txt" -append utf8
可以使用以下代码获取没有BOM的UTF8
$MyFile | Out-File -Encoding ASCII
ASCII
编码不是UTF-8,但它也不是当前的ANSI代码页 - 您想到的应该是默认值(Default)
; ASCII
确实是7位ASCII编码,其中代码点>= 128会被转换为文字?
。 - mklement0ASCII
在这个API中实际上指的是默认的单字节编码,通常在Windows中也是如此。是的,它与官方的ASCII定义不同步,但只是历史遗留问题。 - ForNeVeR-Encoding ASCII
确实只是7位ASCII:'äb' | out-file ($f = [IO.Path]::GetTempFilename()) -encoding ASCII; '?b' -eq $(Get-Content $f; Remove-Item $f)
- ä
已被转换为?
。相比之下,-Encoding Default
(“ANSI”)将正确地保留它。 - mklement0$MyFile = Get-Content $MyPath
$MyFile | Out-File -Encoding "Default" $MyPath
结果是没有BOM的ASCII。
$stdcaltxt | Out-File -encoding utf8 -FilePath $stdCalFileName
和 2)Set-Content -Path $stdCalFileName -Value $stdcaltxt -Encoding utf8
两者都产生了不同的编码 UTF8-BOM 和 USC2 LE BOM,根据 Notepad++ 编码检查! - JGFMK