У меня проблема с выводом в groovy-скрипте. Например, этот код:
def rusAlphabet = 'АБВГДЕЁЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ'
def lowerCaseRusAlphabet = 'абвгдеёжзийклмнопрстуфхцшщъыьэюя'
println(rusAlphabet)
println(rusAlphabet.toLowerCase())
println(lowerCaseRusAlphabet)
принты:
AБВГДЕ?ЖЗИЙКЛМ?ОПРСТУФХЦЧШЩЪЫЬЭЮЯ
a??
абвгдеёжзийклмнопр?туфхцшщъыь?ю?
Он отлично работает со сценариями Python. Я работаю на Windows 10 x64.
В CMD и PowerShell кириллица отображалась в виде вопросов. Затем я проверил «Бета-версия: использовать Unicode UTF-8 для поддержки языков по всему миру» в административных настройках региона. Теперь работает нормально, символы отображаются нормально. Но не для крутых скриптов.
Пробовал этот код в скрипте:
try {
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new InternalError("VM does not support mandatory encoding UTF-8");
}
Он печатает:
AБВГДЕÐ�ЖЗИЙКЛМÐ�ОПРСТУФХЦЧШЩЪЫЬÐЮЯ
að‘ð’ð“ð”ð•ð�ð–ð—ð˜ð™ðšð›ðœð�ðžðÿð ð¡ð¢ð£ð¤ð¥ð¦ð§ð¨ð©ðªð«ð¬ðð®ð¯
абвгдеёжзийклмнопр�туфхцшщъыь�ю�
с этим кодом я получаю AÐ'Ð'ГДЕÐ�ЖЗИЙКЛМÐ�ОПРСТУФХЦЧШЩЪЫ ЬÐЮЯ að'ð'ð“ð”ð•ð�ð–ð—ð˜ð™ðšð›ðœð�ðžðÿð ð¡ð¢ð£ð¤ð¥ð¦ð§ð¨ð©ðªð «ð¬ðð®ð¯ абвгдÐμÑ'жзийклмнопрÑ�туфхцшщъыьÑ� СН�
У вас пока нет ответов, поэтому отредактируйте свой вопрос, чтобы показать код, в котором вы опробовали идею этого ответа. Консоль/терминал, используемый для запуска программы, также может иметь значение.
Вы столкнулись с случаем моджибаке (пример на Python из-за его универсальной понятности): 'AБВГД'.encode( 'utf-8').decode( 'cp1252')
возвращает 'AБВГД'
(используется просто короткая подстрока). В качестве примечания: вы используете A
(U+0041, латинская заглавная буква A) и a
(U+0061, латинская строчная буква A) вместо А
(U+0410, кириллическая заглавная буква A) и а
(U+0430, Кириллическая строчная буква А) соответственно.
Я использую кириллические буквы А
и а
. Проблема не только в этих буквах, вы можете увидеть, что Ё
, Н
, с
, э
и я
интерпретированы неправильно.
Я уверен, что в A
есть латынь def rusAlphabet = 'A
. В def lowerCaseRusAlphabet = 'а
действительно кириллица а
, извините. Пожалуйста, отредактируйте свой вопрос, чтобы предоставить минимально воспроизводимый пример.
Я ожидал, что ваша активация общесистемной поддержки UTF-8 (кодовая страница Windows 65001
) решит вашу проблему, поскольку она устанавливает кодовую страницу OEM и ANSI на 65001
, что должно сделать все устаревшие (не Unicode) программы «говорят в UTF-8».
Обратите внимание, что активация этой функции, хотя и удобна, имеет далеко идущие последствия и может привести к нарушению устаревшего кода: см. этот ответ для получения дополнительной информации.
Если вы не используете эту функцию, помимо обеспечения того, чтобы исходный код читался как UTF-8, требуется следующее (см. следующий важный пункт):
Как показано в этом ответе, упомянутом в комментариях, вы должны переключить stdout и stderr (стандартный поток вывода и стандартные потоки ошибок) на UTF-8:[1]
System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, "UTF-8"));
System.setErr(new PrintStream(new FileOutputStream(FileDescriptor.err), true, "UTF-8"));
Вам также необходимо выполнить следующее, чтобы сеанс PowerShell последовательно использовал UTF-8 (см. этот ответ для получения дополнительной информации):
$OutputEncoding = [Console]::InputEncoding = [Console]::OutputEncoding = New-Object System.Text.UTF8Encoding
Ваша проблема подразумевает, что Groovy интерпретирует ваш файл исходного кода (файл сценария) не как UTF-8, а как Windows-1252, которая является кодовой страницей ANSI для американо-английской локали, а также для многих европейских языков.
Groovy, пожалуй, излишне говорить, основан на Java, а версии Java 17 и ниже используют кодовую страницу системы ANSI для интерпретации файлов исходного кода, тогда как v18+ похвально использует UTF-8. Таким образом, если кодовая страница ANSI равна 65001
, то есть UTF-8, это не должно быть проблемой, но, возможно, Java по-другому определяет, что такое активная кодовая страница ANSI.
Однако независимо от того, активировали ли вы общесистемную поддержку UTF-8, вы можете явно указать Groovy/Java интерпретировать исходный код как UTF-8 следующим образом:
groovy `-Dfile.encoding=UTF8 <your-Groovy-script>
`
перед -
, который необходим только при вызове из PowerShell из-за досадной ошибки — см. выпуск GitHub #6291.Альтернативно вы можете настроить эту опцию через переменную среды JAVA_TOOL_OPTIONS
(например, из PowerShell для текущего процесса: $env:JAVA_TOOL_OPTIONS = '-Dfile.encoding=UTF8'
), однако учтите, что Groovy CLI затем выведет сообщение, указывающее на использование переменной среды.
[1] Note: I'm unclear on how to also switch stdin (the standard input stream) to UTF-8 for text-based operations; do tell us if you know.
Большое спасибо за такой подробный ответ. К сожалению, Dfile.encoding
тоже не помогает. Вместо символов отображаются только все вопросы.
Понятно, @mabes. Единственный способ получить только символы ?
в выводе на дисплей — это если общесистемный UTF-8 не действует и System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, "UTF-8"));
не используется в скрипте. Что [Console]::OutputEncoding.WebName
сообщает о вашей системе? И какая у вас версия Java? (& (Join-Path $env:JAVA_HOME\bin java) --version
Мне очень жаль, я действительно забыл, что прокомментировал System.setOut(new PrintStream(new FileOutputStream(FileDescriptor.out), true, "UTF-8"));
строку. С этим все работает нормально.
Не волнуйся, @mabes, спасибо, что согласился. Я обновил ответ, чтобы показать вызовы System.setOut()
, когда UTF-8 не включен во всей системе. Если вы знаете, как сделать то же самое для стандартного ввода (стандартный ввод), сообщите нам об этом.