Кодирование текста между Linux и Windows

Главный вопрос, который у меня есть, заключается в том, как я могу заставить текстовый файл, который у меня есть в Linux, правильно отображаться в PowerShell.

В Linux у меня есть текстовые файлы с некоторыми специальными символами, и на самом деле Блокнот отображает текстовый файл точно так же, как он отображается в Linux:

Вывод блокнота

К сожалению, моя программа печатает на моем терминале Linux, и поэтому мне нужен такой же вывод в моем терминале Windows. Я видел другие ответы, которые

  1. Мне нужно использовать шрифт TrueType, поэтому я использую консоль Lucidia.
  2. на моем устройстве Linux кодировка UTF-8. Согласно каждому ответу, который я могу найти в Интернете, CHCP 65001 переключает кодовую страницу в PowerShell на UTF-8.
  3. Windows Powershell лучше оснащена для отображения содержимого, поэтому, хотя я пытался использовать командную строку, теперь я работаю в PowerShell.

Используя CHCP 65001, а затем набрав

more my_file.txt

отображает это:

результат дополнительной команды

при использовании

Get-Content -Encoding UTF8 my_file.txt

выходы:

результат получения контента

Ни один из этих результатов не является достаточно хорошим, но меня действительно беспокоит, что Get-Content делает здесь что-то другое. Код, который я переношу в windows, написан на Free Pascal, а на Free Pascal я могу предоставить кодовую страницу UTF-8, но это все. Так что, хотя Get-Content и является хорошей командой для проверки способности PowerShell выдавать желаемый результат, мне нецелесообразно ее использовать. В Pascal вывод (который записывается на экран PowerShell) выглядит так:

Паскаль Дисплей

Что тоже плохо, эти строки должны соединяться, потому что они делают это в Linux (и, очевидно, некоторые символы интерпретируются так же, как ?). Однако это может быть проблема с кодовой страницей, выбранной в Pascal, что будет следующим шагом.

Мой вопрос прямо сейчас: как я могу заставить Windows Powershell по умолчанию отображать текстовый файл, как он показан в версии блокнота. Для меня нецелесообразно запускать Get-Content везде в моем коде, поэтому, хотя этот результат кажется более многообещающим, я не могу следовать ему.

В качестве дополнительного вопроса, потому что я не смог найти его нигде в Интернете, какие основные игроки здесь, когда дело доходит до отображения контента, потому что это явно большая история, чем просто кодирование. Почему команды «more» и «Get-Content» отображают разные результаты? И почему Get-Content не может прочитать весь контент? Я предполагал, что UTF-8 является универсальным стандартом, и программы, которые могут читать UTF-8, могут, по крайней мере, фактически прочитать все символы, но все они читают его по-разному.

Ввод в виде текста:

    ╭─────╮
    │     │
  ╭─│───╮ │
  │ │   │ │
  │ │ ╭─│───╮
  │ │ │ │ │ │
╭─│───│─╯ │ │
│ │ │ │   │ │
│ │ ╰─╯   │ │
│ │       │ │
│ ╰───────│─╯
│         │
╰─────────╯

В ответ на ответ, опубликованный ниже, я вижу, что

more my_file.txt

производит

дополнительный вывод команды с использованием OutputEncoding

когда используешь

$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding = 
  New-Object System.Text.UTF8Encoding 

person Kraigolas    schedule 17.03.2020    source источник
comment
@AdminOfThings этот результат совпадает с выводом Get-Content.   -  person Kraigolas    schedule 17.03.2020
comment
Итак, я вижу, что gc $file -Encoding UTF8 получает символы, которые были опубликованы в вашем сообщении. Я также вижу, что функция ReadAllText .net, опубликованная AdminOfThings, имеет тот же результат. Кажется, он правильно получает содержимое.   -  person shadow2020    schedule 17.03.2020


Ответы (1)


  • Убедитесь, что ваш текстовый файл в кодировке UTF-8 имеет спецификацию. В противном случае ваш файл будет неправильно интерпретирован Windows PowerShell как закодированный на основе на активной кодовой странице системы ANSI (тогда как PowerShell [Core] 6+ теперь, к счастью, постоянно по умолчанию использует UTF-8 при отсутствии спецификации).

    • В качестве альтернативы используйте Get-Content -Encoding Utf8 my_file.txt, чтобы явно указать кодировку файла.

    • Подробное обсуждение кодировки символов в Windows PowerShell и PowerShell [Core] см. в этом ответе.

  • Чтобы выходные данные из внешних программ правильно записывались в переменную или правильно перенаправлялись в файл, вам нужно установить [Console]::OutputEncoding в кодировку символов, которую данная программа использует при выводе (однако для простой печати на дисплей это может не понадобиться):

    • Если действует кодовая страница 65001 (UTF-8), и ваша программа учитывает это, вам необходимо установить [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding; см. ниже, как убедиться, что 65001 действительно работает, учитывая, что запуск chcp 65001 из PowerShell неэффективен.

    • Вы упоминаете FreePascal, чья поддержка Unicode описана здесь.
      Однако из вашего снимка экрана следует, что ваш Вывод программы FreePascal не UTF-8, поскольку символы со скругленными углами были перекодированы в ? символов (что предполагает перекодирование с потерями в кодовую страницу OEM системы, где эти символы отсутствуют).

    • Таким образом, чтобы решить вашу проблему, вы должны убедиться, что ваша программа FreePascal либо безоговорочно выводит кодировку UTF-8, либо учитывает активную кодовую страницу (как сообщает chcp), при условии, что вы сначала установили значение 65001 (кодовая страница UTF-8; см. ниже).

  • Выберите шрифт, который может отображать символы Юникода со скругленными углами (например, (U+256D) в окне консоли; шрифт Windows PowerShell по умолчанию, Lucinda Console, не может (он отображает введите здесь описание изображения, как показано в вашем вопросе), но, например, Consolas (который PowerShell [Core] 6+ использует по умолчанию), может.


Последовательное использование кодировки UTF-8 с внешними программами:

Примечание.

  • Приведенная ниже команда не является необходимой и не влияет на команды PowerShell, такие как командлет Get-Content.

  • Некоторые устаревшие консольные приложения, в частности more.com (которые Windows PowerShell оборачивает в more функцию), фундаментально не поддерживают Unicode, только устаревший OEM-код. страниц.[*]

Согласно каждому ответу, который я могу найти в Интернете, CHCP 65001 переключает кодовую страницу в PowerShell на UTF-8.

chcp 65001 не работает при запуске из внутри PowerShell, поскольку .NET кэширует значение [Console]::OutputEncoding при запуске сеанса PowerShell, с кодовой страницей, которая действовала в то время.

Вместо этого вы можете использовать следующее, чтобы полностью настроить консольное окно на UTF-8 (что неявно также делает chcp отчет 65001 впоследствии):

$OutputEncoding = [console]::InputEncoding = [console]::OutputEncoding =
                    New-Object System.Text.UTF8Encoding

Это заставляет PowerShell интерпретировать выходные данные внешней программы как UTF-8, а также кодировать данные, которые он отправляет в внешней программе, как UTF-8 (благодаря переменной предпочтения $OutputEncoding).

См. этот ответ для получения дополнительной информации.


[*] При действующей кодовой странице UTF-8 65001 more незаметно пропускает строки, содержащие хотя бы один символ Unicode, который не может быть сопоставлен с кодовой страницей OEM системы (любой символ, отсутствующий в однобайтовой кодовой странице OEM системы, которая может представлять только 256 символов), что в данном случае применяется к строкам, содержащим символы с закругленными углами, такие как (НА ЧЕРТЕЖАХ СВЕТ ДУГА ВНИЗ И ВПРАВО, U+256D).

person mklement0    schedule 17.03.2020