javac 编译文件使用的编码方式
1. javac在控制台编译java类文件
通常,我们手动建立一个java文件(记事本),并保存时,默认编码为ANSI编码(注意不是ASCII编码)。在中文操作系统中就是GBK编码,日文操作系统中就是MS932编码。
(在windows命令行中输入chcp,显示当前编码。)
在命令行中用javac编译时,如果不指定-encoding选项,默认是采用操作系统的编码。如果在中文或者日文操作系统中,java源文件的格式是UTF-8的话,则两种格式不符就会报错。
例1:HelloEncodingUTF8.java(java源文件编码格式为:UTF-8)
(源文件路径为:C:\javacode_encoding\src\com\hpe\kevin\HelloEncodingUTF8.java)
package com.hpe.kevin;
public class HelloEncodingUTF8 {
public static void main(String[] args) {
System.out.println("お疲れ様です。張です。");
}
}
在源文件所在目录以外的目录进行编译,且不指定encoding选项(编译时默认编码为:MS932)。
C:\Users\junzhang>chcp
現在のコード ページ: 932
C:\Users\junzhang>SET CLASSPATH
環境変数 CLASSPATH が定義されていません
C:\Users\junzhang>dir C:\javacode_encoding\src
C:\javacode_encoding\src のディレクトリ
2019/05/17 16:28
2019/05/17 16:28
2019/05/17 16:28
0 個のファイル 0 バイト
3 個のディレクトリ 134,084,251,648 バイトの空き領域
C:\Users\junzhang>dir C:\javacode_encoding\src\com\hpe\kevin
C:\javacode_encoding\src\com\hpe\kevin のディレクトリ
2019/05/17 16:28
2019/05/17 16:28
2019/05/17 16:27 164 HelloEncodingUTF8.java
1 個のファイル 164 バイト
2 個のディレクトリ 134,084,247,552 バイトの空き領域
C:\Users\junzhang>javac -d C:\javacode_encoding\class C:\javacode_encoding\src\com\hpe\kevin\HelloEncodingUTF8.java
C:\javacode_encoding\src\com\hpe\kevin\HelloEncodingUTF8.java:6: エラー: この文字は、エンコーディングMS932にマップできません
System.out.println("縺顔夢繧梧ァ倥〒縺吶?ょシオ縺ァ縺吶??");
^
C:\javacode_encoding\src\com\hpe\kevin\HelloEncodingUTF8.java:6: エラー: この文字は、エンコーディングMS932にマップできません
System.out.println("縺顔夢繧梧ァ倥〒縺吶?ょシオ縺ァ縺吶??");
^
C:\javacode_encoding\src\com\hpe\kevin\HelloEncodingUTF8.java:6: エラー: この文字は、エンコーディングMS932にマップできません
System.out.println("縺顔夢繧梧ァ倥〒縺吶?ょシオ縺ァ縺吶??");
^
エラー3個
C:\Users\junzhang>
很明显发生了乱码。
接下来,由于源文件的编码是UTF-8,所以我们在编译时指定编码为UTF-8。
C:\Users\junzhang>javac -d C:\javacode_encoding\class -encoding UTF-8 C:\javacode_encoding\src\com\hpe\kevin\HelloEncodingUTF8.java
C:\Users\junzhang>
指定了编码后,编译正常终了。
题外话:在编译时加上-encoding选项这个解决办法虽然有效,但是每次编译时都要加,很麻烦。一劳永逸的办法就是设置JAVA_TOOL_OPTIONS环境变量,值为“-Dfile.encoding=UTF-8”。这样在新开命令行窗口,再次输入javac命令进行编译时,就不需要加-encoding选项了。
接着,我们来运行生成的class文件。
由于没有设定classpath,所以我们在运行class文件时,必须加上-classpath或者-cp选项。
C:\Users\junzhang>dir C:\javacode_encoding\class\com\hpe\kevin
C:\javacode_encoding\class\com\hpe\kevin のディレクトリ
2019/05/17 16:37
2019/05/17 16:37
2019/05/17 16:37 475 HelloEncodingUTF8.class
1 個のファイル 475 バイト
2 個のディレクトリ 134,081,228,800 バイトの空き領域
C:\Users\junzhang>java -cp C:\javacode_encoding\class com.hpe.kevin.HelloEncodingUTF8
お疲れ様です。張です。
C:\Users\junzhang>
很幸运没有出现乱码!!!
但是如果将打印的内容改成中文的,源文件编码不变(还是为UTF-8),结果会怎样呢?
例2:HelloEncodingUTF8_2.java(java源文件编码格式为:UTF-8)
(源文件路径为:C:\javacode_encoding\src\com\hpe\kevin\HelloEncodingUTF8_2.java)
编译时同样指定编码为UTF-8,运行class文件时不指定编码,结果如下:
C:\Users\junzhang>dir C:\javacode_encoding\src\com\hpe\kevin\
C:\javacode_encoding\src\com\hpe\kevin のディレクトリ
2019/05/17 16:47
2019/05/17 16:47
2019/05/17 16:27 164 HelloEncodingUTF8.java
2019/05/17 16:46 160 HelloEncodingUTF8_2.java
2 個のファイル 324 バイト
2 個のディレクトリ 134,078,070,784 バイトの空き領域
C:\Users\junzhang>javac -d C:\javacode_encoding\class -encoding UTF-8 C:\javacode_encoding\src\com\hpe\kevin\HelloEncodingUTF8_2.java
C:\Users\junzhang>java -cp C:\javacode_encoding\class com.hpe.kevin.HelloEncodingUTF8_2
?好,我叫?洛琳。
C:\Users\junzhang>
很遗憾,中文的“你”和“张”变成了乱码!!!
这是什么原因呢?很简单,因为出力打印内容的CMD控制台的编码是MS932的。在MS932中,找不到中文字符“你”和“张”。
那要如何才能正确显示呢?
首先,要将CMD窗口的Active code page改成UTF-8(代码:65001)
C:\Users\junzhang>chcp 65001
Active code page: 65001
C:\Users\junzhang>
然后再运行类文件时指定编码:-Dfile.encoding=UTF-8
Active code page: 65001
C:\Users\junzhang>java -Dfile.encoding=UTF-8 -cp C:\javacode_encoding\class com.hpe.kevin.HelloEncodingUTF8_2
你好,我叫张洛琳。
C:\Users\junzhang>
恭喜,乱码消失了!!!
2. Eclipse中编译java文件。
将Eclipse的编码设置成UTF-8的方法。
在菜单导航栏上Window-->Preferences 打开"首选项"对话框,左侧导航树,导航到 General-->Workspace
修改Text file encoding部分,点击Other,然后选择UTF-8。
这样修改完成后,每个项目中的java源文件的编码就是UTF-8。这样编译也从没有问题,也没有出现过乱码。正是因为这样才掩盖了使用javac可能出现的乱码。那么Eclipse是如何正确编译文件编码为UTF-8的java源文件的呢?唯一的解释就是Eclipse自动识别了我们java源文件的文件编码,然后采取了正确的encoding参数来编译我们的java源文件。功劳都归功于IDE的强大了。
同样的,运行时没有出现乱码问题也是因为IDE帮我们选择好了编码。如下图:
3. 使用Ant来编译java文件。
Ant也是常用的编译java文件的工具。首先,必须知道Ant在后台其实也是采用javac来编译java源文件的,那么可想而知,1会出现的问题在Ant中也会存在。如果我们使用Ant来编译UTF-8编码的java源文件,并且不指定如何编码,那么也会出现乱码的情况。所以Ant的编译命令有一个属性” encoding”允许我们指定编码,如果我们要编译源文件编码为UTF-8的java文件,那么我们的命令应该如下:
指定了编码也就相当于”javac –encoding”了,所以不会出现乱码了。
4. 使用Gradle来编译java文件。(命令行窗口下)
解决办法就是在build.gradle文件中添加如下一段,然后Gradle将文件识别为UTF-8编码。
tasks.withType(JavaCompile) {
options.encoding = "UTF-8"
}
查阅官方文档,对于Gradle来说编码这个属性默认情况下是null,也就是Gradle会根据你操作系统的版本来选择编码。
上面这个解决办法虽然有效,但是对于每个Gradle项目都需要插入这么一段,很麻烦。还有一种办法可以一劳永逸的指定编码,那就是使用环境变量。在Windows下,新建GRADLE_OPTS环境变量,值为-Dfile.encoding=utf-8。然后新开一个终端窗口再次使用gradle命令,就会发现这下Gradle已经可以正确识别编码了。