Проблемы кодирования IntelliJ IDEA в проекте Gradle - PullRequest
0 голосов
/ 24 марта 2020

Обычно я не задаю здесь вопросов, но проблемы, с которыми я сталкиваюсь, настолько велики ie, что я больше не могу бороться с ними в одиночку, я измотан. Во всяком случае, я собираюсь описать все, что я нашел, и я нашел много интересных вещей, в которые я хочу верить, поможет кто-то мне помочь.

Версии программного обеспечения: - ОС: Windows 10 Pro версия: 1909 сборка: 18363.720 - IntelliJ IDEA: 2019.2.4 Ultimate - версия Gradle-оболочки: 5.2.1-all - jdk: 8

Проблема лежит в кодировках, особенно в выводе консоли в проекте Gradle.

Вот мой файл build.gradle:

plugins {
    id 'java'
    id 'idea'
    id 'application'
}

group 'com.diceeee.mentoring'
version 'release'

sourceCompatibility = 1.8
application.mainClassName('D')
compileJava.options.encoding = 'utf-8'

tasks.withType(JavaCompile) {
    options.encoding = 'utf-8'
}

repositories {
    mavenCentral()
    jcenter()
}

dependencies {
    testCompile group: 'junit', name: 'junit', version: '4.12'
}

Мои исходники находятся в кодировке UTF-8 с CRLF, поэтому в build.gradle я установил, что исходники должны быть скомпилированы с utf-8 кодировка вместо моей системы по умолчанию windows -1251 кодировка.

Вот D. java:

import java.io.FileWriter;
import java.io.IOException;

public class D {
    public static void main(String[] args) throws IOException {
        System.out.println(System.getProperty("file.encoding"));

        String testLine = "Проверка работоспособности И Ш";
        System.out.println(testLine);

        FileWriter writer = new FileWriter("D:\\test.txt");
        writer.write(testLine);
        writer.close();
    }
}

Также у меня есть gradle.properties с одной строкой:

org.gradle.jvmargs=-Dfile.encoding=utf-8

Я проверил, работает ли он, и убедился, что он работает, кодировка Encoder в System.out действительно изменилась на utf-8.

Когда я запускаю свой проект gradle, я получаю следующее:

21:04:53: Executing task 'D.main()'...

> Task :compileJava UP-TO-DATE
> Task :processResources NO-SOURCE
> Task :classes UP-TO-DATE

> Task :D.main()
UTF-8
�������� ����������������� � �

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.2.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 0s
2 actionable tasks: 1 executed, 1 up-to-date
21:04:54: Task execution finished 'D.main()'.

Приходит больше информации. 1) Не случайно я оставил вывод в файле в коде. Если мы попытаемся просмотреть файл, мы увидим следующее:

Проверка работоспособности И Ш

Я не уверен, правильно ли это, но я пришел к выводу, что проблема лежит где-то в консоли, потому что, если будет проблема при кодировке по умолчанию средство записи файлов использовало неправильную кодировку для файла, и выходные данные были бы равны. Но этого не происходит.

2) Я отлаживал внутренние компоненты классов PrintStream, OutputStreamWriter и StreamEncoder. StreamEncoder действительно использует кодировку utf-8, а также кодирует текст utf-8 в правильную последовательность байтов: String testLine = "Проверка работоспособности И Ш"; Каждая буква кириллицы c составляет 2 байта, пробелы - 1 байт, если мы посчитаем все буквы, мы получим 57.

Теперь посмотрите здесь: Экран отладки кодировщика с результирующими байтами

Итак, как мы видим, мы получаем эти первые 57 байтов (остальные взяты из других входных данных, ограничения использования буфера):

[-48, -97, -47, -128, -48, -66, -48, -78, -48, -75, -47, -128, -48, -70, -48, -80, 32, -47, -128, -48, -80, -48, -79, -48, -66, -47, -126, -48, -66, -47, -127, -48, -65, -48, -66, -47, -127, -48, -66, -48, -79, -48, -67, -48, -66, -47, -127, -47, -126, -48, -72, 32, -48, -104, 32, -48, -88, 91]

выглядит правильно, буквы кириллицы c закодированы как [ -48, -97], [-47, -128] и другие группы по 2 байта, поэтому выглядит красиво, пробелы тоже совпадают. Итак, кодировщик делает большую работу, он работает, но что тогда происходит? Я не знаю. Шутки в сторону. Но есть больше информации. Если это не показалось ошеломляющим, я приготовил кое-что еще для вас.

Я создал чистый Java проект без каких-либо gradle / maven et c, только мой собственный jdk и ничего более. Программа такая же:

package com.company;

import java.io.FileWriter;
import java.io.IOException;

public class Main {

    public static void main(String[] args) throws IOException {
        System.out.println(System.getProperty("file.encoding"));

        String testLine = "Проверка работоспособности И Ш";
        System.out.println(testLine);

        FileWriter writer = new FileWriter("D:\\test.txt");
        writer.write(testLine);
        writer.close();
    }
}

Я ее запускаю и что я получу?

"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\lib\idea_rt.jar=58901:C:\Program Files\JetBrains\IntelliJ IDEA 2019.2.4\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;C:\Users\<my_removed_name>\IdeaProjects\test\out\production\test" com.company.Main
UTF-8
Проверка работоспособности И Ш

Process finished with exit code 0

И после этого я просто умер. Wtf происходит ??? Вернемся к проекту gradle. Я сделал небольшую модификацию:

import java.io.FileWriter;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

public class D {
    public static void main(String[] args) throws IOException {
        System.out.println(System.getProperty("file.encoding"));

        String testLine = new String("Проверка работоспособности И Ш".getBytes(StandardCharsets.UTF_8), "windows-1251");
        System.out.println(testLine);

        FileWriter writer = new FileWriter("D:\\test.txt");
        writer.write(testLine);
        writer.close();
    }
}

И теперь вывод:

21:43:06: Executing task 'D.main()'...

> Task :compileJava
> Task :processResources NO-SOURCE
> Task :classes

> Task :D.main()
UTF-8
Проверка работоспособности �? Ш

Deprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/5.2.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 0s
2 actionable tasks: 2 executed
21:43:06: Task execution finished 'D.main()'.

В файле:

Проверка работоспособности � Ш

Кроме того, этот вывод в консоли является первым вещь, которая подтолкнула меня, чтобы определить, что идет не так, я просто кодировал и обнаружил, что что-то действительно не так с кириллицей c «И». Я пытался решить это, и снова, и снова ... и теперь я здесь, потому что я в тупике, я перепробовал все, что я нашел в аналогичных вопросах и темах о проблемах кодирования, у меня есть красный некоторые статьи о кодировке по умолчанию в java, о том, что Windows использует кодировку cp866 в консоли, кодировку windows -1251 по умолчанию, что нам нужно явно определить кодировку с -Dfile.encoding = UTF-8, ничего не помогает, я даже не знаю, что искать, чтобы найти проблему. Я думал, что gradle не распознает свойство, и кодировка по-прежнему windows -1251, но отладка показала, что я был не прав.

Итак, вот полный список вещей, которые я пытался решить: 1) Установить -Dfile.encoding = UTF-8 в файлах idea.exe.vmoptions и idea64.exe.vmtions с перезапуском. Не помогло 2) Установите UTF-8 в IntelliJ IDEA -> Настройки -> Редактор -> Кодировки файлов везде. Не помогло 3) Установите кодировку компилятора gradle в utf-8. Не помогло 4) Установите опцию gradle jvm org.gradle.jvmargs = -Dfile.encoding = utf-8. Не помогло 5) Проверено, что Windows имеет русский язык по умолчанию для программ, которые не поддерживают Unicode для поддержки кириллицы c. Не помогло.

Я не уверен, в чем проблема с gradle, потому что чистый проект без gradle работает отлично, вывод на консоль в порядке. Но с Gradle символы кириллицы c неверны. Кроме того, я попытался как-то исправить вывод на консоль с помощью getBytes (charset) и нового метода / конструктора String (byte [], charset), я попробовал следующие варианты:

String testLine = new String("Проверка работоспособности И Ш".getBytes(StandardCharsets.UTF_8), "windows-1251");

Output:
Проверка работоспособности �? Ш

Не работает.

String testLine = new String("Проверка работоспособности И Ш".getBytes(StandardCharsets.UTF_8), "cp866");

Output:
?�?�???????�???? ?�???????�???�?????�?????????�?�?? ?� ?�

Не работает.

String testLine = new String("Проверка работоспособности И Ш".getBytes(StandardCharsets.UTF_8), "utf-8");

Output:
�������� ����������������� � �

Результат, который мы получаем без каких-либо преобразований.

Кроме того, я попробовал еще одну вещь - обертку System.out для установки другой кодировки консоли.

public class D {
    public static void main(String[] args) throws IOException {
        System.out.println(System.getProperty("file.encoding"));

        System.setOut(new PrintStream(System.out, true, "utf-8"));
        String testLine = "Проверка работоспособности И Ш";
        System.out.println(testLine);

        FileWriter writer = new FileWriter("D:\\test.txt");
        writer.write(testLine);
        writer.close();
    }
}

И у нас все еще ничего нет, даже не изменилось:

> Task :D.main()
UTF-8
�������� ����������������� � �

Ну, по всей этой информации, я думаю, что с консолью что-то не очень хорошо сам по себе, потому что даже при последнем выполнении приведенного выше кода этот вывод выводится в файле:

Проверка работоспособности И Ш

Это кодировка utf-8, это правильный вывод. Но System.out.println печатает что-то иррациональное в консоли, даже если Encoder работает хорошо. Я не знаю, что происходит (извините за грязные разговоры), если проблема действительно в градле, как это проверить? Или как позволить gradle использовать другую кодировку для вывода на консоль? Или, может быть, это все еще что-то с IntelliJ IDEA, даже если вывод в проекте без Gradle правильный?

Я чувствую себя детективом, но я застрял, застрял в этом случае. Я благодарен, если кто-нибудь мне поможет.

Ответы [ 2 ]

0 голосов
/ 01 мая 2020

Run \ Edit Configurations, выберите конфигурацию запуска и введите -Dfile.encoding=UTF-8 в поле VM Options. Это решенная проблема для меня.

0 голосов
/ 25 марта 2020

Измените шрифт на тот, который способен правильно отображать все символы в Настройках (Настройки в macOS) | Редактор | Шрифт | Шрифт Настройки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...