STDIN и Powershell - Как сделать так, чтобы кодировка соответствовала?
У меня проблема с Ruby (1.9.3) и Powershell.
Мне нужно написать интерактивное консольное приложение, которое будет обрабатывать предложения на польском языке. Мне помогли и я могу получить элементы ARGV с польскими диакритическими знаками, но стандартный ввод не работает так, как я хочу.
Иллюстрация кода:
# encoding: UTF-8
target = ARGV[0].dup.force_encoding('CP1250').encode('UTF-8')
puts "string constant = dupą"
puts "dupą".bytes.to_a.to_s
puts "dupą".encoding
puts "target = " +target
puts target.bytes.to_a.to_s
puts target.encoding
puts target.eql? "dupą"
STDIN.set_encoding("CP1250", "UTF-8")
# the line above changes nothing, it can be removed and the result is still the same
# I obviously wanted to mimic the ARGV solution
target2 = STDIN.gets
puts "target2 = " +target2
puts target2.bytes.to_a.to_s
puts target2.encoding
puts target2.eql? "dupą"
Выход:
string constant = dupą
[100, 117, 112, 196, 133]
UTF-8
target = dupą
[100, 117, 112, 196, 133]
UTF-8
true
dupą //this is fed to STDIN.gets
target2 = dup
[100, 117, 112]
UTF-8
false
Очевидно, Руби никогда не получает четвертого персонажа из STDIN.gets. Если я напишу более длинную строку, как dupąlalala
все еще только три начальных байта появляются в программе.
- Я попытался перечислить байты и зацикливаться на getc, но кажется, что они никогда не достигают Ruby (где они потерялись?)
- Я использовал chcp 65001 (кажется, ничего не меняет)
Я изменил свой $OutputEncoding на [Console]::OutputEncoding; теперь это выглядит так:
IsSingleByte : True BodyName : ibm852 EncodingName : Środkowoeuropejski (DOS) HeaderName : ibm852 WebName : ibm852 WindowsCodePage : 1250 IsBrowserDisplay : True IsBrowserSave : True IsMailNewsDisplay : False IsMailNewsSave : False EncoderFallback : System.Text.InternalEncoderBestFitFallback DecoderFallback : System.Text.InternalDecoderBestFitFallback IsReadOnly : True CodePage : 852
Я использую шрифт Consolas
Что мне делать, чтобы правильно читать польские диакритические знаки в Powershell?
2 ответа
Я узнал некоторую соответствующую информацию. Не уверен, что это именно правильная информация. Но, эй, у ОП уже есть другое решение.
# Get "encoding" for code page 1250 (Central European)
$en=[System.Text.Encoding]::GetEncoding(1250)
# Looks like this:
IsSingleByte : True
BodyName : iso-8859-2
EncodingName : Central European (Windows)
HeaderName : windows-1250
WebName : windows-1250
WindowsCodePage : 1250
IsBrowserDisplay : True
IsBrowserSave : True
IsMailNewsDisplay : True
IsMailNewsSave : True
EncoderFallback : System.Text.InternalEncoderBestFitFallback
DecoderFallback : System.Text.InternalDecoderBestFitFallback
IsReadOnly : True
CodePage : 1250
# Change STDIN's input encoding
[console]::InputEncoding=$en
$x = Read-Host
# I typed in dupą
# (I set Polish in Languate Bar.
# Final letter is apostrophe on US English keyboard)
[int[]][char[]]$x
# output is: 100 117 112 261 (in hex): 64 75 70 105
# the final character (261) is "Latin Small Letter A with Ogonek"
.Net 4.x ожидает и создает метку порядка байтов (BOM) с CHCP 65001 (UTF-8) на стандартном вводе.
Кажется, это исправлено в .Net Core, но требует изменения
Console.StandardInputEncoding
в 4.x, чтобы правильно перехватывать связь с дочерними процессами, у которых нет подобных предположений.