Приведение int к символам в Powershell дает неожиданные результаты - PullRequest
0 голосов
/ 19 октября 2018

Я пытаюсь сгенерировать строки с 1 из каждого символа ASCII.Я начал с

32..255| %{[char]$_ | Out-File -filepath .\outfile.txt -Encoding ASCII -Append}

Я ожидал список печатных символов , но я получил другие символы.

Может кто-нибудь указать мне или лучший способ получить мой ожидаемый результат или объяснение, почему я получаю эти результаты?

1 Ответ

0 голосов
/ 19 октября 2018
[char[]] (32..255) | Set-Content outfile.txt

В Windows PowerShell это создаст файл, закодированный в формате ANSI.Термин кодировка "ANSI" представляет собой зонтичный термин для набора однобайтовых 8-битовых кодировок фиксированной ширины в Windows, которые являются надмножеством из ASCII-кодировка .Используемая специфическая кодировка "ANSI" подразумевается кодовой страницей , связанной с устаревшим системным языком , действующим в вашей системе. [1] ;например, Windows-1252 в англо-американских системах.

См. Нижний раздел о том, почему следует избегать кодирования "ANSI".

Если вы должны сделать то же самое в PowerShell Core ,вы получите файл с кодировкой UTF-8 без BOM , который является наилучшей кодировкой для межплатформенной и кросс-локальной совместимости.

В Windows PowerShell добавление -Encoding utf8 также даст вам файл UTF-8, но с BOM.
Если вы используете -Encoding Unicode или просто используете оператор перенаправления > или Out-File,вы получите файл, кодированный UTF-16LE .
(В PowerShell Core , напротив, > по умолчанию создает UTF-8 без спецификации, потому чтопоследняя является последовательно применяемой кодировкой по умолчанию).

Примечание: С строками и числами , Set-Content и > / Out-File может бытьиспользуется взаимозаменяемо (кроме кодировки в Windows PowerShell);для других типов только > / Out-File дает значимые представления, хотя и подходит только для глазных яблок человека, а не для программной обработки - см. этот ответ для получения дополнительной информации.

Кодовые точки ASCII ограничены 7-битными значениями , т. Е. Диапазоном 0x0 - 0x7f (127).

Следовательно, ваши входные значения 128 - 255не может быть представлен как символы ASCII, и использование -Encoding ASCII приводит к замене недопустимых символов ввода на литерал ? символов (кодовая точка 0x3f / 63), в результате чегов потере информации.


Важно :

В памяти , номера литья, такие как 32(0x20) или 255 (0xFF) до [char] (System.Char) приводит к тому, что числа интерпретируются как UTF-16 кодединицы , представляющие символы Unicode [2] , такие как U+0020 и U+00FF как 2-байтовые последовательности с использованием собственного байтаПорядок, потому что это символы в .NET.
Аналогично, экземпляры .NET [string] типа System.String являются последовательностями из одного или нескольких [char] экземпляров.

При выводе в файл или во время сериализации перекодирование этих строк UTF-16 может происходить , в зависимости от подразумеваемой или указанной выходной кодировки.

  • Если выходное кодирование является фиксированной однобайтовой кодировкой, такой как ASCII, Default ("ANSI") или OEM, потеря информацииможет произойти , а именно, если строка для вывода содержит символы, которые не могут быть представлены в целевой кодировке.

  • Выберите один из Unicode -основанные форматы кодирования , гарантирующие, что:

    • информация не теряется ,
    • результирующий файл интерпретируется одинаково во всех системах , независимо от локали системы.
    • UTF-8 является наиболее широко признаннымкодирование, но обратите внимание, что Windows PowerShell (в отличие от PowerShell Core) неизменно добавляет BOM к таким файлам, что может вызвать проблемы на Unix-подобных платформах и с утилитами наследия Unix;это формат, ориентированный и оптимизированный для обратной совместимости с кодировкой ASCII, который использует от 1 до 4 байтов для кодирования одного символа.
    • UTF-16LE (который PowerShell называет Unicode) - это прямое представление единиц кода в памяти, но обратите внимание, что каждый символ кодируется (как минимум) 2 байт, что приводит к удвоению размера файлов UTF-8 для строк, которые в основном содержат символы в диапазоне ASCII.
    • UTF-16BE (чтоВызов PowerShell bigendianunicode) меняет порядок байтов в каждой единице кода.
    • UTF-32LE (который PowerShell вызывает UTF32), представляет каждый символ Unicode в виде фиксированной 4-байтовой последовательности;даже больше, чем с UTF-16, это обычно приводит к излишне большим файлам.
    • UTF-7 следует вообще избегать, поскольку он не является частью стандарта Unicode.

[1] Среди устаревших кодовых страниц, поддерживаемых в Windows, есть также фиксированные двухбайтовые и переменные ширины кодировки, но только для восточноазиатских локалей;иногда они (неправильно) совместно именуются DBCS (двухбайтовый набор символов), в отличие от SBCS (однобайтовый набор символов);см. список всех кодовых страниц Windows .

[2] Строго говоря, код UTF-16 единица идентифицирует код Unicode точка , но не каждая кодовая точка сама по себе является полным символом Юникода, поскольку некоторые (редкие) символы Юникода имеют значение кодовой точки, выходящее за пределы диапазона, который может быть представлен 16-разрядным целым числом, и этикодовые точки могут альтернативно , представленные последовательностью 2 других кодовых точек, известных как суррогатные пары .

...