分类: Java
2007-02-12 21:17:19
一、java源码的编辑,编译。//070212 未完待续
编辑一个java源文件a.java:
class a {
public static void main(String[] args) {
String s = "世世世世世世";
System.out.println(s);
}
}
在windows xp中文版中,(默认file.encoding=GBK) 编译OK。
在linux 中,locale环境为 LANG=en_US; LC_ALL=C 时,编译出错:
a.java:3: warning: unmappable character for encoding ASCII
String s = "????????????";
^
这是为什么呢?
java的class文件使用的是UTF-8编码。
a.java被编译到a.class 的过程,包含到 UTF-8编码转换的过程。
在这里,就是从 C -> UTF-8。
The locale "C" or "POSIX" is a portable locale; its LC_CTYPE part corresponds to the 7-bit ASCII character set.
计算机是以数字作为处理对象。所以java源码里的字符在被处理之前,计算机要将它转换成相应的数字。这种 字符-数字 的对应关系可以理解为character set。
locale C的字符集只定义了数字0~127所对应的字符,也就是说 > 0x7F 的数值,它就不认识了。(红色的数字)
sh-3.00# hexdump -C a.java
00000000 63 6c 61 73 73 20 61 20 7b 0a 09 70 75 62 6c 69 |class a {..publi|
00000010 63 20 73 74 61 74 69 63 20 76 6f 69 64 20 6d 61 |c static void ma|
00000020 69 6e 28 53 74 72 69 6e 67 5b 5d 20 61 72 67 73 |in(String[] args|
00000030 29 20 7b 0a 09 09 53 74 72 69 6e 67 20 73 20 3d |) {...String s =|
00000040 20 22 ca c0 ca c0 ca c0 ca c0 ca c0 ca c0 22 3b | "............";|
00000050 0a 09 09 53 79 73 74 65 6d 2e 6f 75 74 2e 70 72 |...System.out.pr|
00000060 69 6e 74 6c 6e 28 73 29 3b 0a 09 7d 0a 7d 0a |intln(s);..}.}.|
解决方法:
1 加上编译选项 -encoding charset, charset可为任意 定义了0~255对应字符 的字符集。
2 设置Locale.
验证class文件里的编码
选择charset为 iso88591 来编译, locale环境为 LANG=en_US; LC_ALL=en_US.iso88591
sh-3.00# hexdump -C a.class
00000000 ca fe ba be 00 00 00 31 00 1d 0a 00 06 00 0f 08 |漱壕...1........|
00000010 00 10 09 00 11 00 12 0a 00 13 00 14 07 00 15 07 |................|
00000020 00 16 01 00 06 3c 69 6e 69 74 3e 01 00 03 28 29 |........()|
00000030 56 01 00 04 43 6f 64 65 01 00 0f 4c 69 6e 65 4e |V...Code...LineN|
00000040 75 6d 62 65 72 54 61 62 6c 65 01 00 04 6d 61 69 |umberTable...mai|
00000050 6e 01 00 16 28 5b 4c 6a 61 76 61 2f 6c 61 6e 67 |n...([Ljava/lang|
00000060 2f 53 74 72 69 6e 67 3b 29 56 01 00 0a 53 6f 75 |/String;)V...Sou|
00000070 72 63 65 46 69 6c 65 01 00 06 61 2e 6a 61 76 61 |rceFile...a.java|
00000080 0c 00 07 00 08 01 00 18 c3 8a c3 80 c3 8a c3 80 |........????|
00000090 c3 8a c3 80 c3 8a c3 80 c3 8a c3 80 c3 8a c3 80 |????????|
000000a0 07 00 17 0c 00 18 00 19 07 00 1a 0c 00 1b 00 1c |................|
000000b0 01 00 01 61 01 00 10 6a 61 76 61 2f 6c 61 6e 67 |...a...java/lang|
000000c0 2f 4f 62 6a 65 63 74 01 00 10 6a 61 76 61 2f 6c |/Object...java/l|
000000d0 61 6e 67 2f 53 79 73 74 65 6d 01 00 03 6f 75 74 |ang/System...out|
000000e0 01 00 15 4c 6a 61 76 61 2f 69 6f 2f 50 72 69 6e |...Ljava/io/Prin|
000000f0 74 53 74 72 65 61 6d 3b 01 00 13 6a 61 76 61 2f |tStream;...java/|
00000100 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d 01 00 |io/PrintStream..|
00000110 07 70 72 69 6e 74 6c 6e 01 00 15 28 4c 6a 61 76 |.println...(Ljav|
00000120 61 2f 6c 61 6e 67 2f 53 74 72 69 6e 67 3b 29 56 |a/lang/String;)V|
00000130 00 20 00 05 00 06 00 00 00 00 00 02 00 00 00 07 |. ..............|
00000140 00 08 00 01 00 09 00 00 00 1d 00 01 00 01 00 00 |................|
00000150 00 05 2a b7 00 01 b1 00 00 00 01 00 0a 00 00 00 |..*?.?........|
00000160 06 00 01 00 00 00 01 00 09 00 0b 00 0c 00 01 00 |................|
00000170 09 00 00 00 2b 00 02 00 02 00 00 00 0b 12 02 4c |....+..........L|
00000180 b2 00 03 2b b6 00 04 b1 00 00 00 01 00 0a 00 00 |?.+?.?.......|
00000190 00 0e 00 03 00 00 00 03 00 03 00 04 00 0a 00 05 |................|
000001a0 00 01 00 0d 00 00 00 02 00 0e |..........|
000001aa
sh-3.00# echo -n 世 | iconv -f iso88591 -t utf8 | hexdump -C
00000000 c3 8a c3 80 |??|
00000004
sh-3.00# echo -n ?|iconv -f iso88591 -t utf8 |hexdump -C
00000000 c3 8a |?|
00000002
// 上面命令中的?,是在secureCRT中输入汉字“世”,然后删掉后半个汉字。
参考:
* O'Reilly - Learning Java, 3rd Edition
* man 3 setlocale
* 车东 强烈推荐