Var*_*uss 9 java encoding utf-8 intellij-idea gradle
通常情况下,我不会在这里提问,但我面临的问题是如此诡异,我无法再独自对抗,我已经筋疲力尽了。不管怎样,我将描述我所发现的一切,我发现了许多有趣的事情,我想相信这会帮助别人帮助我。
\n\n软件版本:\n - 操作系统:Windows 10 Pro 版本:1909 内部版本:18363.720\n - IntelliJ IDEA:2019.2.4 Ultimate\n - Gradle 包装器版本:5.2.1-all\n - jdk:8
\n\n问题在于编码,特别是 Gradle 项目中的控制台输出。
\n\n这是我的 build.gradle 文件:
\n\nplugins {\n id \'java\'\n id \'idea\'\n id \'application\'\n}\n\ngroup \'com.diceeee.mentoring\'\nversion \'release\'\n\nsourceCompatibility = 1.8\napplication.mainClassName(\'D\')\ncompileJava.options.encoding = \'utf-8\'\n\ntasks.withType(JavaCompile) {\n options.encoding = \'utf-8\'\n}\n\nrepositories {\n mavenCentral()\n jcenter()\n}\n\ndependencies {\n testCompile group: \'junit\', name: \'junit\', version: \'4.12\'\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n我的源代码采用带有 CRLF 的 UTF-8 编码,因此在 build.gradle 中我设置源代码应使用 utf-8 编码而不是系统默认的 windows-1251 编码进行编译。
\n\n这是D.java:
\n\nimport java.io.FileWriter;\nimport java.io.IOException;\n\npublic class D {\n public static void main(String[] args) throws IOException {\n System.out.println(System.getProperty("file.encoding"));\n\n String testLine = "\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8";\n System.out.println(testLine);\n\n FileWriter writer = new FileWriter("D:\\\\test.txt");\n writer.write(testLine);\n writer.close();\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n我也有 gradle.properties 一行:
\n\norg.gradle.jvmargs=-Dfile.encoding=utf-8\n
Run Code Online (Sandbox Code Playgroud)\n\n我检查了它是否有效,并向自己保证它有效,System.out 中的 Encoder 编码确实更改为 utf-8。
\n\n当我运行我的 gradle 项目时,我得到这个:
\n\n21:04:53: Executing task \'D.main()\'...\n\n> Task :compileJava UP-TO-DATE\n> Task :processResources NO-SOURCE\n> Task :classes UP-TO-DATE\n\n> Task :D.main()\nUTF-8\n\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd \xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd \xef\xbf\xbd \xef\xbf\xbd\n\nDeprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.\nUse \'--warning-mode all\' to show the individual deprecation warnings.\nSee https://docs.gradle.org/5.2.1/userguide/command_line_interface.html#sec:command_line_warnings\n\nBUILD SUCCESSFUL in 0s\n2 actionable tasks: 1 executed, 1 up-to-date\n21:04:54: Task execution finished \'D.main()\'.\n
Run Code Online (Sandbox Code Playgroud)\n\n有更多信息。\n1) 我将输出留在代码文件中并非巧合。如果我们尝试查看文件,我们可以看到:
\n\n\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8\n
Run Code Online (Sandbox Code Playgroud)\n\n我不确定它是否正确,但我得出的结论是问题出在控制台的某个地方,因为如果默认编码存在问题,文件编写器对文件使用了错误的编码,并且输出将是相等的。但这并没有发生。
\n\n2) 我已经调试了 PrintStream、OutputStreamWriter 和 StreamEncoder 类的内部结构。StreamEncoder 确实使用 utf-8 字符集,还将 utf-8 文本编码为正确的字节序列:\nString testLine = "\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80 \xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0 \xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8";\n每个西里尔字母为 2 个字节,空格为 1 个字节,如果我们数一下所有字母,得到 57 个。
\n\n现在,请看这里:\n带有结果字节的编码器调试屏幕
\n\n因此,正如我们所看到的,我们得到了前 57 个字节(其他来自其他输入,缓冲区使用限制):
\n\n[-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]\n
Run Code Online (Sandbox Code Playgroud)\n\n它看起来很正确,西里尔字母编码为 [-48, -97], [-47, -128] 和其他 2 字节组,所以看起来不错,空格也匹配。所以,编码器做得很好,它有效,但是接下来发生了什么?\n我不知道。严重地。但还有更多信息。如果这看起来不令人兴奋,我还为你准备了其他东西。
\n\n我创建了一个干净的Java项目,没有任何gradle/maven等,只有我自己的jdk,仅此而已。\n程序是相同的:
\n\npackage com.company;\n\nimport java.io.FileWriter;\nimport java.io.IOException;\n\npublic class Main {\n\n public static void main(String[] args) throws IOException {\n System.out.println(System.getProperty("file.encoding"));\n\n String testLine = "\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8";\n System.out.println(testLine);\n\n FileWriter writer = new FileWriter("D:\\\\test.txt");\n writer.write(testLine);\n writer.close();\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n我运行它,我会得到什么?
\n\n"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\nUTF-8\n\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8\n\nProcess finished with exit code 0\n
Run Code Online (Sandbox Code Playgroud)\n\n在那之后,我就死了。发生了什么事情???暂时回到 gradle 项目。我做了一点修改:
\n\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.nio.charset.StandardCharsets;\n\npublic class D {\n public static void main(String[] args) throws IOException {\n System.out.println(System.getProperty("file.encoding"));\n\n String testLine = new String("\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8".getBytes(StandardCharsets.UTF_8), "windows-1251");\n System.out.println(testLine);\n\n FileWriter writer = new FileWriter("D:\\\\test.txt");\n writer.write(testLine);\n writer.close();\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n现在的输出是:
\n\n21:43:06: Executing task \'D.main()\'...\n\n> Task :compileJava\n> Task :processResources NO-SOURCE\n> Task :classes\n\n> Task :D.main()\nUTF-8\n\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xef\xbf\xbd? \xd0\xa8\n\nDeprecated Gradle features were used in this build, making it incompatible with Gradle 6.0.\nUse \'--warning-mode all\' to show the individual deprecation warnings.\nSee https://docs.gradle.org/5.2.1/userguide/command_line_interface.html#sec:command_line_warnings\n\nBUILD SUCCESSFUL in 0s\n2 actionable tasks: 2 executed\n21:43:06: Task execution finished \'D.main()\'.\n
Run Code Online (Sandbox Code Playgroud)\n\n在文件中:
\n\n\xd0\xa0\xd1\x9f\xd0\xa1\xd0\x82\xd0\xa0\xd1\x95\xd0\xa0\xd0\x86\xd0\xa0\xc2\xb5\xd0\xa1\xd0\x82\xd0\xa0\xd1\x94\xd0\xa0\xc2\xb0 \xd0\xa1\xd0\x82\xd0\xa0\xc2\xb0\xd0\xa0\xc2\xb1\xd0\xa0\xd1\x95\xd0\xa1\xe2\x80\x9a\xd0\xa0\xd1\x95\xd0\xa1\xd0\x83\xd0\xa0\xd1\x97\xd0\xa0\xd1\x95\xd0\xa1\xd0\x83\xd0\xa0\xd1\x95\xd0\xa0\xc2\xb1\xd0\xa0\xd0\x85\xd0\xa0\xd1\x95\xd0\xa1\xd0\x83\xd0\xa1\xe2\x80\x9a\xd0\xa0\xd1\x91 \xd0\xa0\xef\xbf\xbd \xd0\xa0\xd0\x81\n
Run Code Online (Sandbox Code Playgroud)\n\n另外,控制台中的这个输出是促使我确定出了什么问题的第一件事,我只是在编码,发现西里尔文“\xd0\x98”确实有问题。我试图解决它,一次又一次......现在我在这里,因为我陷入了死胡同,我尝试了在有关编码问题的类似问题和主题中找到的所有内容,我有一些关于java中默认编码的红色文章,Windows在控制台中使用cp866编码,默认为windows-1251编码,我们需要使用-Dfile.encoding=UTF-8显式确定编码,没有任何帮助,我不甚至知道要寻找什么来发现问题。我以为 gradle 无法识别属性并且字符集仍然是 windows-1251,但调试显示我错了。
\n\n好吧,这里是我尝试解决问题的完整列表:\n1) 在 idea.exe.vmoptions 和 idea64.exe.vmoptions 中设置 -Dfile.encoding=UTF-8 并重新启动。没有帮助。\n2) 在 IntelliJ IDEA -> 设置 -> 编辑器 -> 文件编码中到处设置 UTF-8。没有帮助。\n3) 将 gradle 编译器编码设置为 utf-8。没有帮助。\n4) 设置 gradle jvm 选项 org.gradle.jvmargs=-Dfile.encoding=utf-8。没有帮助。\n5) 检查 Windows 是否将俄语作为不支持 unicode 的西里尔语支持的程序的默认语言。没有帮助。
\n\n我不确定 gradle 有什么问题,因为没有 gradle 的干净项目效果很好,控制台输出没问题。但对于 gradle,西里尔字母符号不正确。另外,我尝试使用 getBytes(charset) 和 new String(byte[], charset) 方法/构造函数以某种方式更正控制台的输出,我尝试了这些变体:
\n\nString testLine = new String("\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8".getBytes(StandardCharsets.UTF_8), "windows-1251");\n\nOutput:\n\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xef\xbf\xbd? \xd0\xa8\n
Run Code Online (Sandbox Code Playgroud)\n\n不工作。
\n\nString testLine = new String("\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8".getBytes(StandardCharsets.UTF_8), "cp866");\n\nOutput:\n?\xef\xbf\xbd?\xef\xbf\xbd???????\xef\xbf\xbd???? ?\xef\xbf\xbd???????\xef\xbf\xbd???\xef\xbf\xbd?????\xef\xbf\xbd?????????\xef\xbf\xbd?\xef\xbf\xbd?? ?\xef\xbf\xbd ?\xef\xbf\xbd\n
Run Code Online (Sandbox Code Playgroud)\n\n不工作。
\n\nString testLine = new String("\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8".getBytes(StandardCharsets.UTF_8), "utf-8");\n\nOutput:\n\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd \xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd \xef\xbf\xbd \xef\xbf\xbd\n
Run Code Online (Sandbox Code Playgroud)\n\n我们得到的结果没有任何转换。
\n\n另外,我还尝试了一件事,就是 System.out 包装器来设置另一个控制台编码。
\n\npublic class D {\n public static void main(String[] args) throws IOException {\n System.out.println(System.getProperty("file.encoding"));\n\n System.setOut(new PrintStream(System.out, true, "utf-8"));\n String testLine = "\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8";\n System.out.println(testLine);\n\n FileWriter writer = new FileWriter("D:\\\\test.txt");\n writer.write(testLine);\n writer.close();\n }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n我们仍然没有任何输出,甚至没有改变:
\n\n> Task :D.main()\nUTF-8\n\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd \xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd\xef\xbf\xbd \xef\xbf\xbd \xef\xbf\xbd\n
Run Code Online (Sandbox Code Playgroud)\n\n好吧,根据所有这些信息,我认为控制台本身确实有些不好,因为即使是上面代码的最后一次执行,文件中也有这样的输出:
\n\n\xd0\x9f\xd1\x80\xd0\xbe\xd0\xb2\xd0\xb5\xd1\x80\xd0\xba\xd0\xb0 \xd1\x80\xd0\xb0\xd0\xb1\xd0\xbe\xd1\x82\xd0\xbe\xd1\x81\xd0\xbf\xd0\xbe\xd1\x81\xd0\xbe\xd0\xb1\xd0\xbd\xd0\xbe\xd1\x81\xd1\x82\xd0\xb8 \xd0\x98 \xd0\xa8\n
Run Code Online (Sandbox Code Playgroud)\n\n它是utf-8编码的,它是正确的输出。但是 System.out.println 在控制台中打印一些不合理的内容,即使 Encoder 工作良好。我不知道到底是怎么回事(抱歉说脏话),如果问题确实出在 gradle 中,如何检查?或者如何让gradle使用另一种编码进行控制台输出?或者即使没有 gradle 的项目中的输出是正确的,它仍然是 IntelliJ IDEA 的问题?
\n\n我感觉自己像个侦探,但我陷入了困境,陷入了困境。如果有人帮助我,我会很感激。
\n我遇到了类似的问题。这是 Gradle-IntelliJ-on-non-ascii-language-version-Windows 特定问题。
我通过以下方式解决了这个问题:
systemProp.file.encoding=utf-8
中设置gradle.properties
Settings -> Tools -> Terminal -> Application Settings
并设置cmd.exe /K "chcp 65001"
为“Shell 路径”shell 路径应该是cmd.exe
默认的。
属性文件中的属性值应该有助于在 IntelliJ 上使用 Gradle 工具构建工作,并且 shell 路径设置可以解析集成终端上的编码。
如果您在 IntelliJ 外部使用 cmd,而不是从 IntelliJ 上的集成终端使用 cmd,只需chcp 65001
在控制台上调用即可。这将在 cmd 控制台上设置字符编码UTF-8
。
归档时间: |
|
查看次数: |
7675 次 |
最近记录: |