a) 编码问题主要是由于字节码与字符码的转换
(1) GB2312<o:p></o:p>
多字节字符集,是针对特定区域的特定字符集,GBK是GB2312的补充,包括繁体字符。
(2) Unicode<o:p></o:p>
目的是在同一篇文章中同时出现中文,英文,日文,法文等文字.不再使用各自地区的编码方式,采用全球同一的编码方式,这样就不会同一个bytes,在不同的编码方式中冲突的现象,一个bytes与一个字符关联。
所有的字符都在相同的位置并且有相同的名字
Unicode 是一种字符集,它将世界上的所有字符映射成一个唯一的数字(code point),比如字母 a 对应的数字 0x0041。
Unicode的编码标志头FF FE<o:p></o:p>
最显而易见的两种方法是将 Unicode 文本存储为 2 个 或 4 个字节序列的串. 这两种方法的正式名称分别为 UCS-2 和 UCS-4。<o:p></o:p>
问题:
a. 浪费空间
b.有些程序无法整取读取UCS-2的英文字母,因为多了0x 00
所以,UCS-2 不适合作为 Unicode 的外部编码.
解决办法就是UTF—
(3) utf-8<o:p></o:p>
在 将 Unicode 表示的字符进行存储时,还需要一定的编码方式,比如 UCS-2,它用两个字节来表示 Unicode 编码的字符。而 UTF-8 是 Unicode 字符集的另外一种编码方式,它是变长度的,最多 6 个字节,小于 127 的字符用一个字节表示,与 ASCII 字符集的结果一样,因而具有非常好的兼容性,ASCII 编码下的英语文本不需要修改就可以当作 UTF-8 编码进行处理,应用非常广泛。
<o:p></o:p>
以下是Unicode(UCS-2)和UTF-8之间的转换关系表:
U-00000000 - U-0000007F: 0xxxxxxx
U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
<o:p></o:p>
标记头:EF BB BF
如果没有标记头,则通过所有内容两个字节信息判断是否是utf-8。
110××××× 10××××××,如果不是这正采用本地字符集。
<o:p></o:p>
“你“ 这个字符
GB2312: c4 e3
byte[] gb={(byte) 0xc4,(byte) 0xe3};
String a=new String(gb,"GBK");
unicode: 60 4f
String a="\u4f60";
或
byte[] un={(byte) 0xFF,(byte) 0xFE,(byte) 0x60,(byte) 0x4f};
String a=new String(un,"Unicode");
Utf-8: E4 BD A0
byte[] utf={(byte) 0xE4,(byte) 0xBD,(byte) 0xA0};
String a=new String(utf,"Utf-8");
b) 本地系统设置<o:p></o:p>
JVM的缺省编码方式由系统的“本地语言环境”设置确定,和操作系统的类型无关。
中英文环境下不同LOCALE,java的encoding 不同
file.encoding=ISO-8859-1
user.language=en
user.region=US
<o:p></o:p>
file.encoding=GBK
user.language=zh
user.region=CN
file.encoding属性,这个属性确定了JVM的缺省的编码/解码方式:从而影响应用中所有字节流==>字符流的解码方式 ,字符流==>字节流的编码方式。<o:p></o:p>
<o:p></o:p>
c) Java 输入输出过程中 字节流&字符流的转换<o:p></o:p>
(1) 在Java中,字符都是以Unicode进行存储的.
(2) 编码(encoding)解码(decoding):
encode: String -> bytes[]
source.getBytes(“charset”):根据新编码把字符串转化成bytes,过程是以source的单个字符,在编码对照表中查找相应的字节信息(或者进行算法运算)。得到的字节信息。如果source本身的编码于charset相同,则不为原字节数组。
<o:p></o:p>
注意如果这步,不可以窄化,不能由大转小。否则会发生信息丢失,无法挽回。
如source的编码是GB2312
String source=”你好”;
Byte[] bs=Source.getbytes(“iso-8859-1”);
Bs.length = 2;
这是由于在ISO-8859-1中没有发现0x… 0x…(你)的字符(当然不会有,你在GB2312中是双字节,ISO中是单字节对照表),这时就返回?的字节吗。这是就发生信息丢失。
<o:p></o:p>
decode:Bytes[] -> String
new String(bytes,charset) 把bytes,按照charset进行解码得到字符串。也就是说,把bytes当成当成什么编码进行看待。变为字符数组。注意这个过程不可以大化,不能由下转大
<o:p></o:p>
target=new String(source.getBytes(code1),code2)
一般要保持code1和code2相同,并且code2为要显示的字符集。
或者 new String(source.getBytes(code1),code2);
new String(source.getBytes(code2),code1):
在这个过程中要注意
code1:应该为大类型,不能为小类型.如:iso-8859-1
code2:应该为小类型,不能为大类型.如:utf-8
<o:p></o:p>
String code1="utf-8"; //可以为GBK,utf-8,unicode
String code2="iso-8859-1"; //可以为iso-8859-1\
String b=new String(bb=a.getBytes(code1),code2);
String c=new String(bc=b.getBytes(code2),code1);
所有的应用都是按照字节流=>字符流=>字节流,所以在开发中要对编码解码注意,
不过还是由很多疑问,
1.String有没有方法得到期内存中的二进制编码,
2. String code1="utf-8"; //可以为GBK,utf-8,unicode
String code2="GBK"; //可以为iso-8859-1
if source="你" then 乱码
if source="你们" then 正常
<o:p></o:p>