Powershell 编码文件保存utf8

Powershell 编码文件保存utf8,powershell,Powershell,我的头都碎了:D 我正在尝试编码一个文本文件,该文件将以与记事本保存相同的方式保存 它看起来完全一样,但只有当我通过记事本进入文件并再次保存时,它才是不同的。它对我有效。编码有什么问题?或者我如何解决它?是否有打开记事本并再次保存的命令选项 我现在用 (Get-Content 000014.log) | Out-FileUtf8NoBom ddppyyyyy.txt 在这之后呢 Get-ChildItem ddppyyyyy.txt | ForEach-Object { # get the

我的头都碎了:D 我正在尝试编码一个文本文件,该文件将以与记事本保存相同的方式保存 它看起来完全一样,但只有当我通过记事本进入文件并再次保存时,它才是不同的。它对我有效。编码有什么问题?或者我如何解决它?是否有打开记事本并再次保存的命令选项

我现在用

(Get-Content 000014.log) | Out-FileUtf8NoBom ddppyyyyy.txt
在这之后呢

Get-ChildItem ddppyyyyy.txt | ForEach-Object {
  # get the contents and replace line breaks by U+000A
  $contents = [IO.File]::ReadAllText($_) -replace "`r`n?", "`n"
  # create UTF-8 encoding without signature
  $utf8 = New-Object System.Text.UTF8Encoding $false
  # write the text back
  [IO.File]::WriteAllText($_, $contents, $utf8)
}

当您使用notepad.exe打开文件时,它会自动检测编码(或者您是否以UTF-8格式显式打开文件->打开..?)。如果您的文件实际上不是UFT-8,而是其他文件,则记事本可以解决此问题,并在重新保存文件时将其转换为所需的编码。因此,当您没有在您的PoSh脚本中指定正确的输入编码时,就会出现问题

但这还不是全部;当保存文件以创建常规文本文件时,记事本还会删除错误字符。例如,您的文本文件可能包含一个空字符,只有在使用记事本时才会删除该字符。如果是这种情况,则输入文件不太可能是UTF-8编码的(除非它已损坏)。所以,看起来您的问题是源文件是UTF16或类似文件;尝试找到正确的输入编码并重写它,例如UTF-16到UTF-8

Get-Content file.foo -Encoding Unicode | Set-Content -Encoding UTF8 newfile.foo

试着这样做:

Get-ChildItem ddppyyyyy.txt | ForEach-Object {
  # get the contents and replace Windows line breaks by U+000A
  $raw= (Get-Content -Raw $_ -Encoding UTF8) -replace "`r?`n", "`n" -replace "`0", ""
  # create UTF-8 encoding without BOM signature
  $utf8NoBom = New-Object System.Text.UTF8Encoding $false
  # write the text back
  [System.IO.File]::WriteAllLines($_, $raw, $utf8NoBom)
}
如果您正在努力处理字节顺序标记,最好使用十六进制编辑器手动检查文件头;如上图所示保存文件后检查文件,然后使用Notepad.exe打开文件并以新名称保存文件,不再显示任何区别:

具有BOM表的文件的开头如下所示:

另外,如前所述,虽然您的正则表达式模式应该可以工作,但如果您希望将Windows新行转换为Unix样式,则将CR设置为可选的更为常见和安全:`r?`n

通过使用正确的编码读取文件来记录Als是很重要的;如果您的文件实际上是拉丁文1或其他格式的,那么如果您不小心将其转换为高级格式的UTF-8,您最终将得到一个损坏的文件。
因此,我将
-Encoding UTF8
参数添加到Get-Content Cmdlet中;根据需要进行调整。

当您使用notepad.exe打开文件时,它会自动检测编码(或者您是否以UTF-8格式显式打开文件->打开。如果您的文件实际上不是UFT-8,而是其他文件,则记事本可以解决此问题,并在重新保存文件时将其转换为所需的编码。因此,当您没有在您的PoSh脚本中指定正确的输入编码时,就会出现问题

但这还不是全部;当保存文件以创建常规文本文件时,记事本还会删除错误字符。例如,您的文本文件可能包含一个空字符,只有在使用记事本时才会删除该字符。如果是这种情况,则输入文件不太可能是UTF-8编码的(除非它已损坏)。所以,看起来您的问题是源文件是UTF16或类似文件;尝试找到正确的输入编码并重写它,例如UTF-16到UTF-8

Get-Content file.foo -Encoding Unicode | Set-Content -Encoding UTF8 newfile.foo

试着这样做:

Get-ChildItem ddppyyyyy.txt | ForEach-Object {
  # get the contents and replace Windows line breaks by U+000A
  $raw= (Get-Content -Raw $_ -Encoding UTF8) -replace "`r?`n", "`n" -replace "`0", ""
  # create UTF-8 encoding without BOM signature
  $utf8NoBom = New-Object System.Text.UTF8Encoding $false
  # write the text back
  [System.IO.File]::WriteAllLines($_, $raw, $utf8NoBom)
}
如果您正在努力处理字节顺序标记,最好使用十六进制编辑器手动检查文件头;如上图所示保存文件后检查文件,然后使用Notepad.exe打开文件并以新名称保存文件,不再显示任何区别:

具有BOM表的文件的开头如下所示:

另外,如前所述,虽然您的正则表达式模式应该可以工作,但如果您希望将Windows新行转换为Unix样式,则将CR设置为可选的更为常见和安全:`r?`n

通过使用正确的编码读取文件来记录Als是很重要的;如果您的文件实际上是拉丁文1或其他格式的,那么如果您不小心将其转换为高级格式的UTF-8,您最终将得到一个损坏的文件。 因此,我将
-Encoding UTF8
参数添加到Get-Content Cmdlet中;根据需要进行调整。

更新:问题中的代码没有问题,真正的问题是文件中嵌入了
NUL
字符
,这导致了
R
中的问题,并且隐式删除了在记事本中打开和重新保存的字符,从而解决了问题(假设只需丢弃这些
NUL
s即可正常工作)-另请参见:

因此,按如下方式修改
$contents=…
行可以解决您的问题:

$contents = [IO.File]::ReadAllText($_) -replace "`r`n", "`n" -replace "`0"

注意:问题中的代码使用了来自的
Out-FileUtf8NoBom
功能,该功能允许在Windows PowerShell中保存到BOM较少的UTF-8文件;它现在支持
-UseLF
开关,这将简化OP的命令(尽管存在其他问题):


  • 您的正则表达式中存在一个概念性缺陷,尽管在本例中它是良性的:而不是
    “`r`n?”
    您想要
    “`r`n”
    (或者,用纯正则表达式表示,
    ”\r?\n'
    )以匹配CRLF(
    “`r`n”
    )和LF only(
    “`n”
    )新行

    • 您的正则表达式将改为只匹配CRLF和CR(!)换行符;但是,正如所指出的,如果您的输入文件只包含通常的CRLF换行符(并且不包含独立的CR字符),那么替换操作应该仍然有效

    • 事实上,如果只需要用LF替换CRLF序列,则根本不需要正则表达式:
      -replace“`r`n”,“`n”

  • 假设您的原始输入文件是ANSI编码的,您可以简化方法如下,而无需先调用
    Out-FileUtf8NoBom
    假设Windows PowerShell):

#不需要Out-FileUtf8NoBom-直接处理ANSI编码的文件。
获取ChildItem*SomePattern*.txt | ForEach对象{
#获取内容并确保换行符仅限于LF
#[Text.Encoding]::默认为活动ANSI代码页的编码
#在Windows PowerSh中