我有一个脚本可以用当前年份更新配置文件,但由于某种原因,版权符号没有正确插入。 PowerShell 脚本是带有 BOM 的 UTF-8,JSON 文件是 UTF-8。
工作流程是我从 JSON 文件中读取,更新版权日期,然后再次保存到 JSON 文件。
JSON 文件
info.json
:
{
"CopyrightInfo": "Copyright © CompanyName 1992"
}
PowerShell 脚本的可重现摘录:
$path = "./info.json"
$a = Get-Content $path| ConvertFrom-Json
$a.'CopyrightInfo' = "Copyright $([char]::ConvertFromUtf32(0x000000A9)) CompanyName $((Get-Date).Year)"
$a | ConvertTo-Json | set-content $path
我尝试了很多方法,以上是最新的尝试。在 PowerShell 中打印或在记事本中打开时看起来不错,但任何其他编辑器(Visual Studio Code、SourceTree、Azure DevOps 文件查看器等)它们总是会产生以下结果:
"CopyrightInfo": "Copyright � CompanyName 2022"
如果任何人都可以解释我做错了什么,如果他们还可以添加一种使其正常工作的方法,那就太好了。
我使用的是 PowerShell 版本 5.1.19041.1682
编辑:使用可重现的代码摘录和使用的 PowerShell 版本更新了问题。
假设您正在运行 Windows PowerShell 并且您希望读取输入并将输出创建为 UTF-8 编码:
如果可以创建带有 BOM 的 UTF-8 文件(这是 Windows PowerShell 中的 Set-Content -Encoding utf8
总是创建的文件):
# Note the use of -Encoding utf8 in both statements.
# (In PowerShell (Core) 7+, neither would be needed,
# and Set-Content would create a BOM-*less* UTF-8 file;
# you'd need -Encoding utf8BOM to create one *with* a BOM).
$a = Get-Content -Encoding utf8 $path| ConvertFrom-Json
# ...
$a | ConvertTo-Json | Set-Content -Encoding utf8 $path
没有 BOM 的 UTF-8 文件需要在 Windows PowerShell 中进行更多工作,而它现在是 PowerShell (Core) 7+ 中的一致默认值,利用 - 好奇- 事实上,当给定 New-Item
参数时,(总是)使用该编码创建文件:
-Value
注:
上:PowerShell 自动识别 Unicode BOM,但是在读取源代码和通过 cmdlet 读取文件时,
在 BOM假定使用什么编码取决于 PowerShell 版本,例如通过# (In PowerShell (Core) 7+, -Encoding utf8 wouldn't be needed,
# and Set-Content would create a BOM-*less* UTF-8 file by default.)
$a = Get-Content -Encoding utf8 $path| ConvertFrom-Json
# ...
New-Item -Force -Path $path -Value (($a | ConvertTo-Json) + "`r`n")
:
PowerShell(核心) 假定为
UTF-8在
写入 - 文件内容存储在 .NET 字符串中(由内存中的 UTF-16LE 组成)代码单元),即使数据只是通过管道传递。因此,如果没有指定 Get-Content
参数,则无论数据来自何处,它都是文件写入 cmdlet 自己的默认编码;具体来说:
Windows PowerShell 的
-Encoding
ANSI 编码;不幸的是,其他 cmdlet 有
不同的默认值;值得注意的是,
Set-Content
及其虚拟别名Out-File
,默认为UTF-16LE(“Unicode”)- 有关详细信息,请参阅此答案的底部部分。 幸运的是,PowerShell(核心)现在默认为所有cmdlet
无法重现问题:
>
$Data = @{ CopyrightInfo = "Copyright $([char]::ConvertFromUtf32(0x000000A9)) CompanyName $((Get-Date).Year)" }
$Json = ConvertTo-Json $Data
$Json |Set-Content .\Test.json
$Json = Get-Content -Raw .\Test.json
$Data = ConvertFrom-Json $Json
$Data