`
7wolfs
  • 浏览: 178158 次
  • 性别: Icon_minigender_1
  • 来自: 济南
社区版块
存档分类
最新评论

Java 中的 中文编码

    博客分类:
  • Java
阅读更多
1. java.net.URLEncoder.encode
java.net.URLEncoder.encode是将文本内容进行编码转换,然后将每个字节用16进制表示,每个字节内容转成由%和16进制符号格式组成的内容,为了方便网络传输。
String.getBytes是将文本内容根据指定的字符集直接进行编码转换,不会再进行16进制转换。
客户端发送文本内容到服务器端时,先将内容用URLEncoder以UTF-8进行encode,转成16进制格式,再发送转码过的内容,该内容会被Web Server中默认的字符集(ISO-8859-1)进行编码,Server接收后,为了获取客户端发送的原始文本,需要反向解码。先按ISO-8859-1获取用URLEncoder进行encode过的内容,再按照UTF-8进行URLDecoder.decode,进行16进制反向解码,得到原始文本。

String cnStr = "中文";
		String cnStr1 = "";
		

		cnStr1 = new String(java.net.URLEncoder.encode(cnStr, "UTF-8").getBytes(), "ISO-8859-1");

		System.out.println(java.net.URLDecoder.decode(new String(cnStr1.getBytes("ISO-8859-1"), "UTF-8"), "UTF-8"));
		


2. 通过HttpServletResponse直接输出字符时,为了特殊字符需要指定编码集
通过HttpServletResponse.setCharacterEncoding("utf-8") 方法设置输出流的字符编码,该动作需要在HttpServletResponse.getWriter();之前调用,否则会造成输出流按照默认的编码集进行编码。HttpServletResponse.getWriter()一旦被调用后,输出流的字符编码集即确定下来,无法修改。
参见tomcat 5或6中的javax.servlet.http.HttpServletResponse源代码。

3. String 类中字符串编码处理
String由char数组组成,每个char以unicode编码集中的标准形式存在。
将String转成byte数组时,首先将unicode编码的char按照指定的编码集格式转成byte。
将byte数组转成String时,首先将指定编码集格式的byte序列组装成char数组,生成的char数组构成String。

4. 文件IO输出流中字符编码处理
通过文件端口输出字符,为了保证能处理除英文之外的其他字符,满足兼容性的需要,生成输出流接口时,需指定字符编码集。
OutputStreamWriter osw = new OutputStreamWriter(new  FileOutputStream("test.txt"), "utf-8");  
osw.write("中文");   
osw.close();  


5. 文件IO输入流中字符编码处理
通过文件端口输输入字符,为了保证能处理除英文之外的其他字符,满足兼容性的需要,生成输出流接口时,需指定字符编码集。
StringBuffer buffer = new StringBuffer();
FileInputStream fis = new FileInputStream(targetFile);
InputStreamReader isr = new InputStreamReader(fis, "UTF8");
Reader in = new BufferedReader(isr);
int ch;
while ((ch = in.read()) > -1) {
    buffer.append((char)ch);
}
in.close();
return buffer.toString();


6. 页面前端编码与服务端解码的字节内容的交互
场景:
页面调用两次js 的encodeURI方法进行字符编码用post方式提交,服务器端(tomcat、struts、spring)使用java.net.URLDecoder.decode(getRequest().getParameter("jsonStr"),"UTF-8")对他进行解码。
流程:
以中文字符的‘中’字为例:‘中’字的UTF-8的编码是:E4B8AD。‘中’字经过js的encodeURI第一次转码后变成以%前缀表示的16进制UTF8编码串(%E4%B8%AD),再次调用js的encodeURI进行第二次编码(encodeURI(encodeURI("中"))),会得到新的编码串%25E4%25B8%25AD,这个编码串里每个字符都作为最小单位的字节以字节流形式通过post方式传递到服务器。

服务器tomcat接受到内容后,服务器内部程序调用org.apache.catalina.connector.Request.getParameter(String name)方法触发对URL中的传入参数的编码集解析(如果parameter尚未解析过,调用parseParameters方法进行解析,该方法会对url后的queryString和post提交的request body内容都进行解析),对字符串内容的具体解析在org.apache.tomcat.util.http.Parameters.processParameters(byte[] bytes, int start, int len, Charset charset)方法中完成。

处理规则参见org.apache.tomcat.util.buf.UDecoder.convert(ByteChunk mb, boolean query)。该方法首先处理有%前缀的字节:遇到%,则会将%后面的两个字节进行16进制转换转成数字并相加,得到一个十进制数字
,该值与ascii字符表中的值相对应,其他不是以%为前缀的普通字符字节则被原封不动的放入结果字节流中。

%25E4%25B8%25AD编码串中的%25经过这一步骤就会转成%字节,最终结果是%E4%B8%AD。处理完%前缀的字节后,将结果字节串%E4%B8%AD传入 new String(data, 0, ox, encoding)中,即使方法中的encoding是UTF-8,字节串%E4%B8%AD也不能被String对象的UTF8编码表所识别。因为他不是UTF8原始字节串,他是‘中’字符在UTF8中以16进制标识、%字符为前缀的一种组合表达方式,要转成能被UTF8编码表能识别的字节流,需要将以%为标识的每组3个字节经过运算转成一个字节,最终转成3个字节,这是‘中’字符在UTF8编码表中实际的字节数,他可以被UTF8编码表解析成对应的可识别的特殊字符‘中’。该运算通过java.net.URLDecoder.decode来完成,他会识别%标识的3个字节为一组的字节流,他一旦发现%后的字节不是合法的16进制范围内的值时,则提示解码错误。

JavaScript的encodeURI方法说明如下:
The encodeURI function returns an encoded URI by replacing all special characters with their corresponding UTF-8 escape sequences.
encodeURI() does not encode the following characters: ~ ! @ # $ & * ( ) = + ; : ' , / ?


7.tomcat服务器下,get方式提交中文时有乱码问题。
首先是get方式提交乱码,修改tomcat的server.xml。在Connector节点添加URIEncoding="UTF-8"
<!--<br/ /> <br/ /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ /> http://www.CodeHighlighter.com/<br/ /> <br/ /> --><Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443" URIEncoding="UTF-8"/>
3
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics