Кодирование с помощью PowerShell - PullRequest
1 голос
/ 05 мая 2020

У меня следующая проблема: представьте, что у меня есть файл UTF8, в котором каждый специальный символ обозначен символом REPLACEMENT_CHARACTER «�». Некоторая часть файла может выглядеть так:

Das hier r�ckg�ngig ist das zu machen r�ckg�ngig: ist bereits geamcht Weitere W�rter gibt ers zu korrigieren Hier noch ein bl �des Wort zwei in einer Zeile Gühte und Gr��e

Я написал сценарий PowerShell, который заменяет REPLACEMENT_CHARCTERS соответствующими специальными символами, например "a", "ü" или " ß ". Исправленный текст, также UTF8, будет выглядеть следующим образом:

Das hier rückgängig ist das zu machen rückgängig: ist bereits geamcht Weitere Wörter gibt ers zu korrigieren Hier noch ein blödes Gröteer und zu

Проблема в том, что программа, в которую я хочу импортировать текст, принимает только файлы в кодировке «Wester European DOS (CP850)». Кстати, это была исходная кодировка, которую программа была экспортирована и импортировала бы без проблем, если бы я не открыл файл, не отредактировал его и не сохранил в UTF8. Итак, вот что произошло:

  1. Я экспортировал файлы из специальной c программы как «Wester European DOS (CP850)». [Примечание: каждый специальный символ здесь имеет свой собственный ЗАМЕНА ЗНАЧЕНИЯ, поэтому импорт будет работать легко и восстановить специальные символы]

  2. Я открыл файл с помощью редактора по своему выбору и редактора обнаружил "UTF8" сам по себе, что неверно. Не узнал, отредактировал файл и сохранил как UTF8. [Теперь каждый специальный символ имеет один и тот же СИМВОЛ ЗАМЕНЫ, его �]

  3. Я обнаружил, что что-то не так, и написал сценарий, который заменяет каждое вхождение � правильным специальным символом в UTF8. [Думаю, не имеет значения, как это делает сценарий, но если да, спросите]

  4. У меня есть исправленный файл UTF8, но, как вы помните, мне нужно импортировать "западноевропейскую DOS" (CP850) "в мою программу. Та же кодировка файла, что и при экспорте файла. Эта кодировка гарантирует, что каждый специальный символ имеет свой собственный уникальный REPLACEMENT_CHARACTER. Итак, как мне вернуться к этому с помощью PowerShell?

Вот еще некоторая информация. Строка, в которой скрипт считывает файл, который я хочу исправить:

$lines = get-content $file -encoding utf8 | select-string $SearchCharacter

Алгоритм проходит через каждую строку и запрашивает любое неправильное слово с символом для исправления и пропускает его, если оно найдено. очередной раз. После того, как все исправления во всех файлах были найдены, он заменяет в al oop вхождения каждого «ключа» (неправильного слова) на каждое «значение» (исправленное слово) в каждом файле на эту строку:

foreach key ...
(Get-Content -encoding utf8 $file) -replace "$key", "$value" | Set-Content -encoding utf8 $file

Я уже пробовал сделать что-то подобное:

foreach key ...
(Get-Content -encoding utf8 $file) -replace "$key", "$value" | Set-Content -encoding OEM $file

Но это приводит к использованию "?" вместо правильного символа:

Das hier r? ckg? ngig ist das zu machen r? ckg? ngig: ist bereits geamcht Weitere W? rter gibt ers zu korrigieren Hier noch ein bl? des Wort zwei в einer Zeile G? hte und Gr ?? e

Есть предложения, как я могу создать файл "Wester European DOS (CP850)" из UTF8?

EDIT:

Эта функция, полученная из http://www.msdynamics.de/viewtopic.php?f=17&t=25726#p138532, решила мою проблему:

Function ConvertAndReplace_UTF8_OEM850
{
Param ([String]$path)
$path = resolve-path $path
$sourceEncoding = [System.Text.Encoding]::GetEncoding(65001)
$targetEncoding = [System.Text.Encoding]::GetEncoding(850)
$textfile = [System.IO.File]::ReadAllText($path, $sourceencoding)
[System.IO.File]::WriteAllText($path, $textfile, $targetencoding)
Write-host "Content in $path converted from UTF-8 to OEM850"
}

1 Ответ

1 голос
/ 05 мая 2020

Учитывая, что вы говорите, что вы исправили файл в кодировке UTF-8 (так, чтобы он содержал исходные символы), все, что вам нужно, это перекодировать файл UTF-8 обратно в кодовую страницу 850 (CP850) :

Если активная кодовая страница OEM вашей системы - 850 (проверьте с помощью chcp):

Set-Content -NoNewline -Encoding OEM $file -Value (Get-Content -Raw -Encoding utf8 $file)

Примечание: (Get-Content -encoding utf8 $file) | Set-Content -Encoding OEM $file тоже работает, но потенциально изменяет используемые последовательности новой строки и всегда добавляет завершающую новую строку, даже если в исходном файле ее не было. Однако этот вариант может быть лучшим выбором в Windows PowerShell v4 и ниже, где -NoNewline не поддерживается.

Если это не или не может считаться равным:

In PowerShell [Core] 6 +, Параметр Set-Content -Encoding теперь принимает номера кодовых страниц:

Set-Content -NoNewline -Encoding 850 $file -Value (Get-Content -Raw -Encoding utf8 $file)

In Windows PowerShell (версии PowerShell до v5.1), прямое использование требуется. NET Framework:

[IO.File]::WriteAllText(
  (Convert-Path $file),
  (Get-Content -Raw -Encoding utf8 $file),
  [Text.Encoding]::GetEncoding(850)
)

Обратите внимание на использование Convert-Path, чтобы гарантировать, что $file преобразован в полный путь, что необходимо , потому что рабочий каталог. NET обычно отличается от каталога PowerShell.


В Windows PowerShell , какие значения параметра -Encoding принимает ограничен фиксированным набором, который включает только активную ANSI (Default) и OEM (OEM) кодовую страницу , в зависимости от языкового стандарта вашей системы ( язык для программ, не поддерживающих Юникод).

В PowerShell [Core] 6+ вы можете передать любую кодовую страницу по номеру или даже System.Text.Encoding экземпляр напрямую .
И наоборот, хотя OEM все еще можно использовать для ссылки на активную кодовую страницу OEM, начиная с v7.0 нет заполнителя для активной ANSI кодовой страницы - это упущение сообщалось в этой проблеме GitHub .

...