修改此脚本的输出,以便将其读取为无 BOM UTF-8

问题描述 投票:0回答:1

我的文件夹中有几个 .csv 文件,第二列为空,我想用尽可能多的同名 + 第 3 列的 csv 文件中的数据来填充它。

示例:

第一个文件.csv

header1,translation,source
first,,"third"
one,,three

firstfile_column3.txt(文件名+_column3.txt)

source
second, fifth
two

firstfileoutput.csv(源代码变成翻译)

header1,translation,source
first,"second, fifth","third"
one,two,three

我能够让它工作,但口音和亚洲字符是错误的。我在 Windows 上使用 Powershell 5,应该修改输出,以便将其读取为无 BOM UTF-8。 尝试编辑最后几个字符串仍然无法解决。

param(
    $SourceDir = $PWD,
    $OutDir = $PWD,
    $OutFileSuffix = "output" # Define the suffix for the output file.
)

# Get all primary CSV files in the source directory.
$csvFiles = Get-ChildItem -Path $SourceDir -Recurse -Filter "*.csv"

foreach ($csvFile in $csvFiles) {
    # Construct the name for the corresponding _column3 file.
    $column3FileName = "{0}_column3.txt" -f $csvFile.BaseName
    $column3FilePath = Join-Path -Path $SourceDir -ChildPath $column3FileName
    
    # Check if the _column3 file exists.
    if (Test-Path $column3FilePath) {
        # Import the primary CSV file and the corresponding _column3 file.
        $primaryCsv = Import-Csv -Path $csvFile.FullName
        $column3Data = Get-Content $column3FilePath
        
        # Assuming the first line in the _column3 file is a header and we skip it.
        $column3Values = $column3Data | Select-Object -Skip 1

        # Update the second column (translation) in the primary CSV with data from the _column3 file.
        for ($i = 0; $i -lt $primaryCsv.Count; $i++) {
            $primaryCsv[$i].translation = $column3Values[$i]
        }

        # Construct the output file path.
        $outputFilePath = Join-Path -Path $csvFile.DirectoryName -ChildPath ("{0}{1}.csv" -f $csvFile.BaseName, $OutFileSuffix)

        # Export the updated CSV data to a new file.
        $primaryCsv | Export-Csv -Path $outputFilePath -NoTypeInformation -Encoding UTF8
    }
    else {
        Write-Warning "Corresponding column3 file not found for $($csvFile.Name)"
    }
}
powershell encoding utf-8 powershell-5.0 byte-order-mark
1个回答
0
投票

为了确保在您的情况下在 Windows PowerShell 中进行一致的、无 BOM 的 UTF-8 处理:

  • 关于阅读

    • 使用

      -Encoding utf8
      确保读取无 BOM 的 UTF-8 文件:

      • Import-Csv -Encoding utf8 $csvFile.FullName
      • Get-Content -Encoding utf8 $column3FilePath
  • 关于写作

    • 避免

      -Encoding utf8
      ,因为它会创建文件带有 BOM

    • 您的

      Export-Csv
      调用需要一个非显而易见的解决方法,这依赖于以下事实:
      New-Item
      确实默认创建无 BOM 的 UTF-8 文件:

       $null = New-Item -Force $outputFilePath -Value (
         $primaryCsv | ConvertTo-Csv -NoTypeInformation | Out-String
       )
      

请注意,这些东西在 PowerShell (Core) 7+ 中都不是必需的,它始终默认为(无 BOM)UTF-8。


背景资料
  • 不幸的是,Windows PowerShell及其文件读取 cmdlet 在缺少 BOM的情况下假设的字符编码表现出不一致行为。

    • 在你的代码中

      Import-Csv
      碰巧假设UTF-8,...

    • ...而

      Get-Content
      假定为 ANSI,即系统的活动遗留 ANSI 代码页,PowerShell 引擎本身在读取 源代码时也是如此。

    • 类似地,写入文件时也没有一致性:

      Set-Content
      使用ANSI编码,而
      Out-File
      (及其虚拟别名,
      >
      >>

  • 相比之下,PowerShell(核心)7+及其cmdlet(包括读取和写入)现在一致默认为(无BOM)UTF-8


结果是:

  • Windows PowerShell 中,为了安全起见,如果您知道自己正在处理 UTF-8 编码的文件

    ,请始终使用 
    -Encoding utf8 - 无论它们是否有 BOM(在前一种情况下,使用
    -Encoding utf8
    在技术上是多余的,但不会造成任何伤害)。

    • 相比之下,PowerShell (Core) 7+ 中不再需要此功能,在没有 BOM 的情况下,假定使用 UTF-8。
  • 如果您想使用 UTF-8 写入文件,同样适用,但请注意,Windows PowerShell

    -Encoding utf8
    总是会创建带有 BOM 的 UTF-8 文件:

    • 请参阅

      此答案了解纯文本解决方法(New-Item

      解决方法如上所示)。

    • 相比之下,_PowerShell (Core) 7+ 创建

      无 BOM UTF-8 文件,默认-Encoding utf8

      ;如果您
      确实想要那里的BOM,请使用-Encoding utf8BOM
      
      

© www.soinside.com 2019 - 2024. All rights reserved.