Примечание. Нижеследующее содержит общую информацию, которая в нормально функционирующей среде PowerShell могла бы объяснить симптом OP. То, что решение не работает в случае OP, связано с машинно-определенными c причинами, которые неизвестны на данный момент.
Чтобы гарантировать, что ваша Java программа получает свой ввод UTF- 8-кодированный без спецификации , необходимо установить $OutputEncoding
на System.Text.UTF8Encoding
экземпляр, который не излучает спецификацию :
# Assigns UTF-8 encoding *without a BOM*.
# PowerShell uses this encoding to encode data piped to external programs.
# $OutputEncoding defaults to ASCII(!) in Windows PowerShell, and more sensibly
# to BOM-*less* UTF-8 in PowerShell [Core] v6+
$OutputEncoding = [Text.UTF8Encoding]::new($false)
Предостережение : НЕ используйте, по-видимому, эквивалентный New-Object Text.Utf8Encoding $false
, поскольку из-за ошибки, описанной в , эта проблема GitHub, он не будет работать, если вы назначите $OutpuEncoding
в неглобальной области, например, в script .
Если, напротив, вы используете [Text.Encoding]::Utf8
(System.Text.Encoding.UTF8
), вы получите спецификацию, что, как я подозреваю, произошло в вашем случае.
Обратите внимание, что эта проблема не связана с источником кодирование любого файла, считываемого Get-Content
, потому что , что отправляется через конвейер PowerShell, никогда не является потоком необработанных байтов , но . NET объектов , что в дело о f Get-Content
означает, что. NET строки отправляются (System.String
, внутренняя последовательность кодовых единиц UTF-16).
Поскольку вы отправляете по трубопроводу на внешнюю программу (в вашем случае - Java), PowerShell символьно кодирует отправляемые ему объекты (stringified-on-demand) на основе переменная предпочтения $OutputEncoding
, и полученная внешняя кодировка - это то, что получает внешняя программа.
Возможно, что удивительно, хотя спецификации обычно используются в файлах , PowerShell учитывает настройку спецификации кодировки, назначенную $OutputEncoding
, а также в конвейере , добавляя ее к первой отправленной строке (только).
См. Нижний раздел из этого ответа для получения дополнительной информации о том, как PowerShell обрабатывает конвейерный ввод и вывод из внешних программ, включая то, как это [Console]::OutputEncoding
, что имеет значение, когда PowerShell интерпретирует данные, полученные из external программы .
Чтобы проиллюстрировать разницу, используя пример программы (обратите внимание, что достаточно использовать строковый литерал PowerShell в качестве входных данных; нет необходимости читать из файла):
# Note the EF BB BF sequence representing the UTF-8 BOM.
# Enclosure in & { ... } ensures that a local, temporary copy of $OutputEncoding
# is used.
PS> & { $OutputEncoding = [Text.Encoding]::Utf8; 'hö' | java Hex }
EF BB BF 68 C3 B6 0D 0A
# Note the absence of EF BB BF, due to using a BOM-less
# UTF-8 encoding.
PS> & { $OutputEncoding = [Text.Utf8Encoding]::new($false); 'hö' | java Hex }
68 C3 B6 0D 0A
В Windows PowerShell , где $OutputEncoding
по умолчанию ASCII (!), вы увидите следующее со значением по умолчанию на месте:
# The default of ASCII(!) results in *lossy* encoding in Windows PowerShell.
PS> 'hö' | java Hex
68 3F 0D 0A
Обратите внимание, что 3F
представляет буквальный символ ?
, который также транслитерируется не-ASCII ö
, учитывая, что он не представлен в ASCII; другими словами: информация была потеряна .
PowerShell [Core] v6 + теперь разумно по умолчанию использует UTF-8 без спецификации, поэтому поведение по умолчанию там, как и ожидалось .
Хотя UTF-8 без спецификации является PowerShell [Core] по умолчанию , также для командлетов, которые читают из файлов и записывают в них, в Windows [Console]::OutputEncoding
по-прежнему отражает активную кодовую страницу OEM по умолчанию начиная с v7.0, поэтому для корректного захвата вывода от внешних программ, генерирующих UTF-8, он также должен быть установлен на [Text.UTF8Encoding]::new($false)
- см. эту проблему GitHub .