JAVA语言具有跨平台,unicode字符集编码的特点。
但是在开发过程中处理数据时涉及到的字符编码问题零零散散,尤其是处理中文字符时一不留神就可能出现一堆奇奇怪怪的符号,俗称乱码。
对于乱码,究其原因,就是因为编码和解码过程中使用了错误的字符编码方案导致的。
首先在开头说明本人对 编码 解码 这两个概念的理解(如有错误烦请dalao指出,如有疑问也欢迎交流,感激不尽!):
首先,有一个字符串:
String str="hello,编码";
使用String类的方法getBytes(String charset);指定一个字符编码方案由字符串str其ByteArray形式,称之为为编码过程:
byte[] b_str = str.getBytes("utf-8");
使用String类重载的构造方法之一String(byte[] b,String charset);指定一个字符编码方案从一个ByteArray生成一个字符串,称之为解码过程:
String str_b = new String(b_str, "utf-8");
类似的,在某些在字节流与字符流之间进行转换工作的类及方法也都如此理解,即:
字符→字节:编码
字节→字符:解码
对于java源文件编码的说明:
在编写java源文件时,可能使用了各种编码,只要在编译时通过编译参数指定使用的编码方案即可
-encoding 字符集
无论是.java还是.jsp,涉及java源码的地方,都需要告知编译器使用哪种字符编码方案来处理该源码。
现在这一工作大多已经由各种集成开发环境代为完成了,但我们仍需对其有一定了解以备不时之需。
对于java程序中的编码:
在一个java程序中,涉及到编码问题地方集中在文件读写,各种输入输出流的使用上,本小节着重分析java程序运行时的编码问题。
在对存储内容为字符的文件进行读写的时候,多数情况下是使用了包装类对文件输入输出流进行了包装。
这些字符读写包装类表面上没有涉及编码问题,实际上包装类产生的字符流在调用底层字节流的时候也是需要将数据在字符-字节间进行相应转换的,只不过默认情况下其采用了平台默认字符编码方案来完成编码-解码过程。
当我们有特殊需要的时候,可以主动控制这一过程,让包装类使用我们指定的字符编码方案进行字符-字节的转换。
此处以,字符流(输出字符的包装类PrintWriter,缓冲读取字符的包装类BufferedReader),底层流(文件IO流)为例:
我们利用在包装类使用Writer或Reader作为参数的构造方法,使用InputStreamReader和OutputStreamWriter两个中间类来指定字符-字节转换使用的字符编码方案
try { File f = new File("d:\\coding.txt"); FileOutputStream fos = new FileOutputStream(f); FileInputStream fis = new FileInputStream(f); PrintWriter pw = new PrintWriter(new OutputStreamWriter(fos, "utf-8")); BufferedReader br = new BufferedReader(new InputStreamReader(fis, "utf-8")); } catch (Exception e) { e.printStackTrace(); }
通过上述代码,我们就实现了使用包装类且使用我们指定的字符编码方案更便捷的进行字符操作。
对于其他的包装的方法与此相同的以字节为基础的流,此处不再赘述。
有一点值得注意:不同的字符编码方案在错误的解码之后可能会丢失字节。
例如奇数个中文字符以UTF-8编码后以GBK解码再编码后再以UTF-8解码导致部分乱码:
try { String str = "哈哈哈"; byte[] encode_by_utf8 = str.getBytes("utf-8"); String decode_by_gbk = new String(encode_by_utf8, "gbk"); byte[] encode_by_gbk = decode_by_gbk.getBytes("gbk"); String decode_by_utf8 = new String(encode_by_gbk, "utf-8"); System.out.println(decode_by_utf8); //Output:哈哈?? } catch (Exception e) { e.printStackTrace(); }
简述其根本原因:两种编码方案对单个中文字符编码时使用的字节数不同导致中间过程中丢失了字节,虽然总体上编码还原了但是边界丢失的字节导致了乱码。
更详细的分析见此文章:http://blog.csdn.net/beyondlpf/article/details/7519786
吃饭去了,回来继续写