`
diandidemeng
  • 浏览: 34637 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

java中文乱码问题一些解决方案和经验(转)

    博客分类:
  • java
阅读更多
1.字节和unicode
java内核是unicode的,就连class文件也是,但是很多媒体,包括文 件/流的保存方式是使用字节流的。因此java要对这些字节流经行转化。char是unicode的,而byte是字节。java中byte/char互 转的函数在sun.io的包中间有。其中ByteToCharConverter类是中调度,可以用来告诉你,你用的convertor。其中两个很常用 的静态函数是
java 代码
  1. publicstaticByteToCharConvertergetDefault();  
  2. publicstaticByteToCharConvertergetConverter(Stringencoding);   
如果你不指定converter,则系统会自动使用当前的encoding,gb平台上用gbk,en平台上用8859_1。
byte——〉char:
"你"的gb码是:0xc4e3,unicode是0x4f60
java 代码
 
  1. Stringencoding="gb2312";  
  2. byteb[]={(byte)'u00c4',(byte)'u00e3'};  
  3. ByteToCharConverterconverter=ByteToCharConverter.getConverter(encoding);  
  4. charc[]=converter.convertAll(b);  
  5. for(inti=0;i<c.length;i++){  
  6. System.out.println(Integer.toHexString(c[i]));  
  7. }   
结果是什么?0x4f60
如果encoding="8859_1",结果又是什么?0x00c4,0x00e3
如果代码改为
java 代码
 
  1. byteb[]={(byte)'u00c4',(byte)'u00e3'};  
  2. ByteToCharConverterconverter=ByteToCharConverter.getDefault();  
  3. charc[]=converter.convertAll(b);  
  4. for(inti=0;i<c.length;i++){  
  5. System.out.println(Integer.toHexString(c[i]));  
  6. }   
结果将又是什么?根据平台的编码而定。
java 代码
 
  1. char——〉byte:  
  2. Stringencoding="gb2312";  
  3. charc[]={'u4f60'};  
  4. CharToByteConverterconverter=CharToByteConverter.getConverter(encoding);  
  5. byteb[]=converter.convertAll(c);  
  6. for(inti=0;i<b.length;i++){  
  7. System.out.println(Integer.toHexString(b[i]));  
  8. }   
结果是什么?0x00c4,0x00e3
如果encoding="8859_1",结果又是什么?0x3f
如果代码改为
java 代码
 
  1. Stringencoding="gb2312";  
  2. charc[]={'u4f60'};  
  3. CharToByteConverterconverter=CharToByteConverter.getDefault();  
  4. byteb[]=converter.convertAll(c);  
  5. for(inti=0;i<b.length;i++){  
  6. System.out.println(Integer.toHexString(b[i]));  
  7. }   
结果将又是什么?根据平台的编码而定。
很多中文问题就是从这两个最简单的类派生出来的。而却有很多类不直接支持把encoding输入,这给我们带来诸多不便。很多程序难得用encoding了,直接用default的encoding,这就给我们移植带来了很多困难。
2.utf-8
utf-8是和unicode一一对应的,其实现很简单
7位的unicode:0_______
11位的unicode:110_____10______
16位的unicode:1110____10______10______
21位的unicode:11110___10______10______10______
大多数情况是只使用到16位以下的unicode:
"你"的gb码是:0xc4e3,unicode是0x4f60
0xc4e3的二进制:
1100,0100,1110,0011
由于只有两位我们按照两位的编码来排,但是我们发现这行不通,因为第7位不是0因此,返回"?"
0x4f60的二进制:
0100,1111,0110,0000
我们用utf-8补齐,变成:
1110,0100,1011,1101,1010,0000
e4--bd--a0
于是返回:0xe4,0xbd,0xa0。
3.string和byte[]
string其实核心是char[],然而要把byte转化成string,必须经过编码。string.length()其实就是char数组的长度,如果使用不同的编码,很可能会错分,造成散字和乱码。
例如:
java 代码
  1. Stringencoding=“”;  
  2. byte[]b={(byte)'u00c4',(byte)'u00e3'};  
  3. Stringstr=newString(b,encoding);   

如果encoding=8859_1,会有两个字,但是encoding=gb2312只有一个字这个问题在处理分页是经常发生。
4.Reader,Writer/InputStream,OutputStream
Reader和Writer核心是char,InputStream和OutputStream核心是byte。但是Reader和Writer的主要目的是要把char读/写InputStream/OutputStream。
例如:
文件test.txt只有一个"你"字,0xc4,0xe3
java 代码
 
  1. Stringencoding="gb2312";  
  2. InputStreamReaderreader=newInputStreamReader(newFileInputStream(  
  3. "text.txt"),encoding);  
  4. charc[]=newchar[10];  
  5. intlength=reader.read(c);  
  6. for(inti=0;i<length;i++){  
  7. System.out.println(c[i]);  
  8. }   
结果是什么?你
如果encoding="8859_1",结果是什么???两个字符,表示不认识。
反过来的例子自己做。
5.我们要对java的编译器有所了解
javac?encoding
我们常常没有用到encoding这个参数。其实encoding这个参数对于跨平台的操作是很重要的。如果没有指定encoding,则按照系统的默认encoding,gb平台上是gb2312,英文平台上是iso8859_1。
java 的编译器实际上是调用sun.tools.javac.main的类,对文件进行编译,这个类有compile函数中间有一个encoding的变量,- encoding的参数其实直接传给encoding变量。编译器就是根据这个变量来读取java文件的,然后把用utf-8形式编译成class文件。
例子代码:
java 代码
 
  1. Stringstr="你";  
  2. FileWriterwriter=newFileWriter("text.txt");  
  3. write.write(str);  
  4. writer.close();   
如果用gb2312编译,你会找到e4bda0的字段;
如果用8859_1编译,00c400e3的二进制:
0000,0000,1100,0100,0000,0000,1110,0011
因为每个字符都大于7位,因此用11位编码:
1100,0001,1000,0100,1100,0011,1010,0011
c1--84--c3--a3
你会找到c184c3a3。
但是我们往往忽略掉这个参数,因此这样往往会有跨平台的问题:
样例代码在中文平台上编译,生成zhclass
样例代码在英文平台上编译,输出enclass
(1).zhclass在中文平台上执行ok,但是在英文平台上不行
(2).enclass在英文平台上执行ok,但是在中文平台上不行
原因:
(1). 在中文平台上编译后,其实str在运行态的char[]是0x4f60,在中文平台上运行,filewriter的缺省编码是gb2312,因此 chartobyteconverter会自动用调用gb2312的converter,把str转化成byte输入到fileoutputstream 中,于是0xc4,0xe3放进了文件。
但是如果是在英文平台下,chartobyteconverter的缺省值是8859_1,filewriter会自动调用8859_1去转化str,但是他无法解释,因此他会输出"?"
(2).在英文平台上编译后,其实str在运行态的char[]是0x00c40x00e3,在中文平台上运行,中文无法识别,因此会出现??;
在英文平台上,0x00c4-->0xc4,0x00e3->0xe3,因此0xc4,0xe3被放进了文件。

 6.其它原因:
<%@pagecontentType="text/html;charset=GBK"%>
设置浏览器的显示编码,如果response的数据是utf8编码,显示将是乱码,但是乱码和上述原因还不一样。


    7.发生编码的地方
从数据库到java程序byte——〉char
从java程序到数据库char——〉byte
从文件到java程序byte——〉char
从java程序到文件char——〉byte
从java程序到页面显示char——〉byte
从页面form提交数据到java程序byte——〉char
从流到java程序byte——〉char
从java程序到流char——〉byte
谢志钢的解决方法:
我是使用配置过滤器的方法解决中文乱码的:

xml 代码
 
  1. <web-app>  
  2. <filter>  
  3. <filter-name>RequestFilter</filter-name>  
  4. <filter-class>net.golden.uirs.util.RequestFilter</filter-class>  
  5. <init-param>  
  6. <param-name>charset</param-name>  
  7. <param-value>gb2312</param-value>  
  8. </init-param>  
  9. </filter>  
  10. <filter-mapping>  
  11. <filter-name>RequestFilter</filter-name>  
  12. <url-pattern>*.jsp</url-pattern>  
  13. </filter-mapping>  
  14. </web-app>  
  15. publicvoiddoFilter(ServletRequestreq,ServletResponseres,  
  16. FilterChainfChain)throwsIOException,ServletException{  
  17. HttpServletRequestrequest=(HttpServletRequest)req;  
  18. HttpServletResponseresponse=(HttpServletResponse)res;  
  19. HttpSessionsession=request.getSession();  
  20. StringuserId=(String)session.getAttribute("userid");  
  21. req.setCharacterEncoding(this.filterConfig.getInitParameter("charset"));//设置字符集?  
  22. 实际上是设置了byte——〉char的encoding  
  23. try{  
  24. if(userId==null||userId.equals("")){  
  25. if(!request.getRequestURL().toString().matches(  
  26. ".*/uirs/logon/logon(Controller){0,1}\x2Ejsp$")){  
  27. session.invalidate();  
  28. response.sendRedirect(request.getContextPath()+  
  29. "/uirs/logon/logon.jsp");  
  30. }  
  31. }  
  32. else{//看看是否具有信息上报系统的权限  
  33. if(!net.golden.uirs.util.UirsChecker.check(userId,"信息上报系统",  
  34. net.golden.uirs.util.UirsChecker.ACTION_DO)){  
  35. if(!request.getRequestURL().toString().matches(  
  36. ".*/uirs/logon/logon(Controller){0,1}\x2Ejsp$")){  
  37. response.sendRedirect(request.getContextPath()+  
  38. "/uirs/logon/logonController.jsp");  
  39. }  
  40. }  
  41. }  
  42. }  
  43. catch(Exceptionex){  
  44. response.sendRedirect(request.getContextPath()+  
  45. "/uirs/logon/logon.jsp");  
  46. }  
  47. fChain.doFilter(req,res);  
  48. }  

分享到:
评论
2 楼 diandidemeng 2007-08-15  
就拿各种浏览器的解码方式来看,你换成utf-8或gb2312,它们的显示结果都不一样...
1 楼 lewisou 2007-08-04  
我对你的解决方法有点疑惑。
request被写死编码是gb2312,如果某个jsp页面的response输出编码是utf-8,那浏览器默认的表单递交编码就是utf-8,而request用gb2313来解析是不是会有乱码?

相关推荐

    java中文乱码解决方案和经验

    ### Java中文乱码解决方案与经验 #### 一、字节与Unicode 在Java中处理文本时,经常会遇到中文乱码的问题。这是因为Java内部使用的是Unicode编码标准,而外部数据源如文件、网络传输等通常使用的是字节流,且可能...

    Java中文乱码浅析及解决方案

    Java 中文乱码问题是一个常见的编程困扰,尤其对于处理中文字符的Java程序而言。这个问题通常源于字符编码的不一致,即不同环节采用的字符编码标准不统一。本文将深入探讨这一问题,并提供相应的解决方案。 首先,...

    java读取txt文件乱码解决方案

    java读取txt文件乱码解决方案java读取txt文件乱码解决方案java读取txt文件乱码解决方案java读取txt文件乱码解决方案java读取txt文件乱码解决方案java读取txt文件乱码解决方案java读取txt文件乱码解决方案java读取txt...

    java中文乱码解决问题

    JAVA 中文乱码解决问题 JAVA 中文乱码问题是开发过程中常见的问题之一,解决这个问题需要了解乱码产生的原因,然后对症下药。下面我们对容易产生乱码问题的场景进行分析,并提出解决方案。 1. 以 POST 方法提交的...

    java Socket与C#通信中中文乱码问题的解决方案

    在Java和C#之间进行Socket通信时,遇到中文乱码问题主要是由于编码格式不一致导致的。Java默认使用UTF-8编码,而C#在处理字符串时可能使用其他编码,如GBK或ASCII。为了解决这个问题,我们需要确保两端在发送和接收...

    Ajax中文乱码问题解决方案

    在IT行业中,Ajax(Asynchronous JavaScript ...通过理解和应用这些解决方案,开发者可以有效地避免和解决Ajax请求中的中文乱码问题,从而提高用户体验。记住,良好的编码习惯和对字符编码的理解是解决此类问题的关键。

    java中文乱码问题详解--- java中文乱码问题详解

    ### Java中文乱码问题详解 #### 一、中文问题的来源与背景 计算机技术发展初期,操作系统主要支持单字节的ASCII字符集。随着全球化进程加快和技术进步,为支持多种语言,尤其是双字节编码的语言(如中文),提出了...

    Java读取TXT文本文件乱码解决方案.doc

    Java 读取 TXT 文本文件乱码解决方案中,主要讨论的是在 Java 中读取 TXT 文本文件时出现乱码的问题,并提供了解决方案。 首先,文章中提供了一个简单的读取 TXT 文件的代码,使用 BufferedReader 和 FileReader ...

    java汉字乱码终极解决代码

    开发中前台页面向后台传参,汉字乱码,看了好多网上的方法都解决不了,所以写了一个工具类,判断是乱码就转换,不乱码就不乱换,汉字字母符号自动判断。最后完美解决汉字乱码问题。

    jsp,java中文乱码问题另类解决方案,jni加密、解密编码

    本篇文章将深入探讨这个问题,并提出一种另类的解决方案——利用JNI(Java Native Interface)进行加密和解密操作来规避乱码问题。 首先,我们需要理解为什么会出现中文乱码。这通常与字符编码有关,Java和JSP默认...

    java中MySQL中文乱码问题解决方案

    Java 中 MySQL 中文乱码问题解决方案 Java 中 MySQL 中文乱码问题是数据库开发中常见的问题之一,解决这个问题需要对数据库、JSP 和 Tomcat 进行相应的设置。下面我们将详细介绍解决该问题的方案。 数据库编码修改...

    JAVA常见中文乱码问题解决方法

    本文深入剖析了Java中文问题的根源,并提供了相应的解决方案。 一、问题的由来 早期的计算机系统主要支持单字节编码的英文字符,但随着多语言需求的增加,Unicode编码应运而生,它能兼容英文和其他多字节字符,如...

    java乱码解决方案

    java乱码解决方案,在使用eclipse时出现的乱码问题,帮助解决

    java中文乱码问题处理方案.docx

    为解决中文乱码问题,历来有多种解决方案,但每种方案都有其优缺点。最传统的方法是通过String的字节码转换处理。这种方法要求开发者直接操作字节流,打破对象的封装性,虽然能解决问题,但在操作上不够方便,且容易...

    彻底解决JAVA读取写入 TXT中文乱码问题 源码

    在Java编程中,读取和写入TXT文件时,经常遇到中文乱码的问题。这是因为Java默认的字符编码可能与TXT文件的实际编码不一致,导致字符无法正确解析。本篇文章将深入探讨这个问题,并提供完整的源码解决方案。 首先,...

    java aspose word 上传到服务器 导出的word 中文字体乱码 的问题 java aspose

    java aspose word 上传到服务器 导出的word 中文字体乱码 的问题 java aspose java aspose word 上传到服务器 导出的word 中文字体乱码 的问题 java aspose java aspose word 上传到服务器 导出的word 中文字体乱码 ...

    中文乱码问题的解决方案以及过滤器

    本篇文章将深入探讨中文乱码问题的成因、解决方案,并介绍如何通过过滤器来有效预防和解决这类问题。 首先,我们需要了解字符编码的基本概念。字符编码是将字符与数字之间建立对应关系的过程,常用的中文编码有GBK...

    java获取乱码问题

    ### Java获取乱码问题解析与解决方案 在Java应用开发过程中,字符编码问题一直是困扰开发者的一大难题,尤其是在处理HTTP请求中的中文或特殊字符时,经常会出现乱码现象。本文将详细介绍如何通过修改`server.xml`...

    彻底解决中文乱码的问题

    然而,每个具体问题可能需要针对性的解决方案,因此在实际工作中,了解并熟练掌握字符编码原理,结合具体情况调整代码,才能真正做到“彻底解决中文乱码问题”。 在提供的压缩包文件“中文乱码的问题决绝.doc”中,...

Global site tag (gtag.js) - Google Analytics