Вставка MS Access UTF-8 со скриптом Powershell - PullRequest
1 голос
/ 20 марта 2020

У меня есть CSV-файл формата UTF-8 с диакритическими знаками Spani sh, если я загружаю его из Access и выбираю UTF-8, все в порядке. Я хочу автоматизировать свою работу, поэтому я сделал скрипт Powershell. Поскольку таблица уже создана, я не могу загрузить данные с SELECT *, но INSERT INTO. С помощью SELECT * я могу указать кодировку UTF-8 как [text;HDR=Yes;CharacterSet=65001;]. Как я могу сделать это с "INSERT INTO"?

Мой код пока (работает, но символы utf-8 gibberi sh):

$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()

Ответы [ 2 ]

1 голос
/ 20 марта 2020

Ваш код правильно запрашивает в сеансе использование кодировки UTF-8 с этим утверждением:

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

См. Документацию к словарю предустановок параметров , реализованных через переменную предпочтения $PSDefaultParameterValues.

Следовательно, в вашем случае -Encoding UTF8 неявно в действии в вызовах любых командлетов с параметром -Encoding, таких как Import-Csv.

Следовательно:

  • Ваш Import-Csv вызов делает прочитайте ваш CSV-файл как UTF-8.

  • Тем не менее, ваш симптом (значения не печатаются правильно в консоли) предполагает, что ваш входной файл CSV на самом деле не является UTF- 8-кодированный .

Таким образом, решение состоит в том, чтобы определить фактическую кодировку файла CSV [1] и передайте его имя параметру
-Encoding
:

Учитывая, что, как вы уже подтвердили, фактическая кодировка вашего файла была ANSI (фиксированное пение кодирование по байтам, определяемое активной устаревшей кодовой страницей вашей системы), используйте имя кодировки Default в Windows PowerShell :

$voters = Import-Csv -Encoding Default -Delimiter ',' -Path C:\Users\Nobody\Desktop\mexico.csv

В PowerShell [Core] 6 + вам действительно нужно передать специфицированный c используемый код ANSI e, который в системах US-Engli sh является Windows-1252, например (список поддерживаемых кодовых страниц см. В документации ; используйте либо значение из столбца «. NET Name», либо число из столбца «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 по непонятным причинам не реализована - см. эту проблему GitHub ; Сделайте так, чтобы ваш голос был услышан там, если вы хотите, чтобы это изменилось.

Для всестороннего обзора поведения кодирования в PowerShell и его изменения между Windows PowerShell (версии вверх до v5.1) и PowerShell [Core] (версии, начиная с v6), см. этот ответ .


[1] Определение кодировки текстового файла:

Примечание. В PowerShell [Core] 6+ Get-Content правильная печать текста файла на экране означает, что все командлеты будут правильно его интерпретировать; к сожалению, из-за крайне непоследовательного поведения командлетов в Windows PowerShell (версии до v5.1), что не всегда верно; Import-Csv является основным примером, потому что по умолчанию используется кодировка ASCII (!) - см. этот ответ для справочной информации.

  • Платформа-спецификация c опции:

    • Windows:

      • Загрузить файл в Блокнот , который при отсутствии Unicode BOM (подпись) пытается автоопределить кодировку и обычно может определить разницу между UTF-8 и ANSI: посмотрите, отображается ли текст правильно, затем посмотрите в правом нижнем углу (строка состояния) на отображаемое имя кодировки, например, «ANSI»; заметьте, однако, что он не сможет сказать вам, что специфицирует c кодовую страницу ANSI , возможно, использовалось (если файл был из другой культуры), потому что это вообще невозможно сделать вывод .
    • Unix -подобные платформы (macOS, Linux, включая WSL):

      • Использовать file утилита (например, file mexico.csv), которая пытается автоматически определить кодировку.
      • Предупреждение : file неверно определяет Windows -1252 как ISO-8859, что не совсем правильно - они в значительной степени совпадают, но не идентичны: см. документы .
  • Кроссплатформенный опции:

    • Передайте файл в Format-Hex (e. g, Format-Hex mexico.csv) до проверить значения байтов ; примечание: обязательно передайте файл в (подразумеваемый) параметр -Path в качестве аргумента , а не передавайте его содержимое через Get-Content в Format-Hex, потому что в последнем case Get-Content, возможно, уже неверно истолковал файл.

    • Используйте Код Visual Studio : пока он не пытается автоматически определить кодировка, предлагает удобный способ перечитать файл с различными кодировками : нажмите на название кодировки в правом нижнем углу (строка состояния; например, «UTF-8») и выберите Reopen with Encoding, затем выберите интересующую кодировку; промойте и повторяйте, пока текст не отобразится правильно.

0 голосов
/ 20 марта 2020

Я реализовал минимальный пример без подключения к БД, поскольку у меня нет MS Access. Можете ли вы указать для параметра -Encoding значение Import-Csv на своем компьютере и посмотреть, работает ли он?

Если этот параметр пропущен, на моем экране отображается gibberi sh.

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
}

слов .csv

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