MS Access 使用 Powershell 脚本插入 UTF-8

MS Access insert UTF-8 with Powershell script

我有一个带有西班牙变音符号的 UTF-8 格式的 CSV 文件,如果我从 Access 加载它并且 select UTF-8 一切都很好。我想自动化我的工作,所以我制作了一个 Powershell 脚本。因为 table 已经创建,所以我无法使用 SELECT *INSERT INTO 加载数据。使用 SELECT * 我可以像 [text;HDR=Yes;CharacterSet=65001;] 一样指定 UTF-8 字符集。我怎样才能用 "INSERT INTO" 做到这一点?

到目前为止我的代码(有效但 utf-8 字符是乱码):

$PSDefaultParameterValues['*:Encoding'] = 'utf8'
$connectstring = "Provider=Microsoft.ACE.OLEDB.12.0; Data Source=C:\Users\Nobody\Desktop\Mexico-test.accdb"
$conn = New-Object System.Data.OleDb.OleDbConnection($connectstring)

$conn.Open()

$Voters = Import-Csv -Delimiter "," -Path "C:\Users\Nobody\Desktop\mexico.csv"

foreach ($Voter in $Voters)
{
    $curp = $Voter.curp
    $age = $Voter.age
    $forename = $Voter.forename
    $middlename = $Voter.middlename
    $surname = $Voter.surname
    $fatherSurname = $Voter.fatherSurname
    $motherSurname = $Voter.motherSurname
    $cmd = $conn.CreateCommand()
    $cmd.CommandText="INSERT INTO voters(curp,age,forename,middlename,surname,fatherSurname,motherSurname) VALUES('$curp','$age','$forename','$middlename','$surname','$fatherSurname','$motherSurname')"
    $cmd.ExecuteNonQuery()
}

$conn.Close()

我实现了一个没有数据库连接的最低限度示例,因为我没有 MS Access。能不能在电脑上给Import-Csv指定-Encoding参数,看看能不能用?

省略此参数会在我的屏幕上呈现乱码。

C??mo est??s

将其显式指定为 UTF8 会呈现此内容。

Cómo estás

$lines = Import-Csv -Delimiter "," -Path "words.csv" -Encoding utf8

foreach ($line in $lines)
{
    $word = $line
    $query = "INSERT INTO voters(word) VALUES('$line')"
    Write-Host $query
}

words.csv

Cómo estás
Dónde estás
quién eres tú
cuando estás llegando

您的代码正确请求 会话范围 使用 UTF-8 编码 并声明:

$PSDefaultParameterValues['*:Encoding'] = 'utf8'

请参阅通过首选项变量 $PSDefaultParameterValues 实现的 参数预设 字典的文档。

因此,在您的情况下,-Encoding UTF8 隐含地 在调用具有 -Encoding 参数的任何 cmdlet 时有效,例如 Import-Csv.

因此:

  • 您的 Import-Csv 调用 确实 将您的 CSV 文件读取为 UTF-8。

  • 但是,您的症状(值未在控制台中正确打印)表明您的 CSV 输入文件实际上不是 UTF-8 编码的

因此,解决方案是确定CSV文件的实际编码[1]将其名称传递给
-Encoding 参数
:

鉴于您已经确认,您的文件的实际编码是 ANSI(由系统的活动遗留代码页确定的固定单字节编码),Windows PowerShell:

中使用Default编码名称
$voters = Import-Csv -Encoding Default -Delimiter ',' -Path C:\Users\Nobody\Desktop\mexico.csv

PowerShell [Core] 6+中,你实际上需要传递特定的 ANSI代码页e 使用,例如在美式英语系统上是 Windows-1252(有关支持的代码页列表,请参阅 the docs;使用“.NET 名称”列中的值或来自 "Identifier" 列的数字,但没有前导 0).

# Use the Windows-1252 ANSI encoding.
$voters = Import-Csv -Encoding 1252 -Delimiter ',' -Path C:\Users\Nobody\Desktop\mexico.csv

注意:从 v7.0 开始,对 Default 编码名称引用活动 ANSI 代码页的支持莫名其妙地没有实现 - 请参阅 this GitHub issue;如果您希望看到改变,请在那里发出您的声音。

有关 PowerShell 中编码行为的全面概述 以及它在 Windows PowerShell(最高版本 v5.1)和 PowerShell [Core](以 v6 开头的版本),请参阅 .


[1] 确定文本文件的编码:

注意:在 PowerShell [Core] 6+ 中,Get-Content 正确打印文件的文本 到屏幕 意味着 all cmdlet 将正确解释它;遗憾的是,由于 Windows PowerShell(最高 v5.1 的版本)中的 cmdlet 行为极其不一致,这不一定是正确的; Import-Csv 是一个很好的例子,因为它默认为 ASCII(!) 编码 - 请参阅 了解背景信息。

  • 平台特定 选项:

    • Windows:

      • 将文件加载到 记事本,在没有 Unicode BOM(签名)的情况下尝试自动检测 编码,通常可以区分 UTF-8 和 ANSI:查看文本是否正确显示,然后在右下角(状态栏)查看正在显示的编码名称,例如, "ANSI";但是请注意,它无法告诉您可能使用了哪些特定的 ANSI 代码页(如果文件来自不同的文化),因为这通常是不可能的推断。
    • 类 Unix 平台(macOS,Linux,包括 WSL):

      • 使用 file 实用程序(例如,file mexico.csv)尝试自动检测编码。
      • 警告file 将 Windows-1252 错误识别为 ISO-8859,这在严格意义上是不正确的 - 它们在很大程度上重叠,但是'相同:参见 the docs.
  • 跨平台 选项:

    • 将您的文件传递给 Format-Hex(例如,Format-Hex mexico.csv)以检查字节值;注意:务必将文件作为 参数 传递给(隐含的)-Path 参数,而不是通过 Get-ContentFormat-Hex,因为在后一种情况下 Get-Content 可能已经误解了文件。

    • 使用Visual Studio Code:虽然它不会尝试自动检测编码,但它提供了一种方便的方法重新读取不同编码的文件:单击右下角附近的编码名称(状态栏;例如,"UTF-8")和select Reopen with Encoding ,然后选择一个感兴趣的编码;冲洗并重复,直到文本显示正确。