java汉字乱码解决办法

自从接触Java和JSP以来,就不断与Java的中文乱码问题打交道,现在终于得到了彻底的解决,现将我们的解决心得与大家共享。

一、Java中文问题的由来

Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面,Java和JSP文件本身编译时产生的乱码问题和Java程序于其他媒介交互产生的乱码问题。

首 先Java(包括JSP)源文件中很可能包含有中文,而Java和JSP源文件的保存方式是基于字节流的,如果Java和JSP编译成class文件过程 中,使用的编码方式与源文件的编码不一致,就会出现乱码。基于这种乱码,建议在Java文件中尽量不要写中文(注释部分不参与编译,写中文没关系),如果 必须写的话,尽量手动带参数-ecoding   GBK或-ecoding   gb2312编译;对于JSP,在文件头加上 <%@   page   contentType= "text/html;charset=GBK "%> 或 <%@   page   contentType= "text/html;charset=gb2312 "%> 基本上就能解决这类乱码问题。

本文要重点讨论的是第二类乱码,即Java程序与其他存储媒介交互时产生的乱码。很多存储媒介,如数据库,文件,流等的存储方式都是基于字节流的,Java程序与这些媒介交互时就会发生字符(char)与字节(byte)之间的转换,具体情况如下:

从页面form提交数据到java程序   byte-> char
从java程序到页面显示   char—> byte

从数据库到java程序   byte—> char
从java程序到数据库   char—> byte

从文件到java程序   byte-> char
从java程序到文件   char-> byte

从流到java程序   byte-> char
从java程序到流   char-> byte

如果在以上转换过程中使用的编码方式与字节原有的编码不一致,很可能就会出现乱码。

二、解决方法

前面已经提到了Java程序与其他媒介交互时字符和字节的转换过程,如果这些转换过程中容易产生乱码。解决这些乱码问题的关键在于确保转换时使用的编码方式与字节原有的编码方式保持一致,下面分别论述(Java或JSP自身产生的乱码请参看第一部分)。

1、JSP与页面参数之间的乱码
JSP 获取页面参数时一般采用系统默认的编码方式,如果页面参数的编码类型和系统默认的编码类型不一致,很可能就会出现乱码。解决这类乱码问题的基本方法是在页 面获取参数之前,强制指定request获取参数的编码方式:request.setCharacterEncoding( "GBK ")或request.setCharacterEncoding( "gb2312 ")。
如果在JSP将变量输出到页面时出现了乱码,可以 通过设置response.setContentType( "text/html;charset=GBK ")或response.setContentType( "text/html;charset=gb2312 ")解决。
如果不想在每个文件里都写这样两句话,更简洁的办法是使用Servlet规范中的过虑器指定编码,过滤器的在web.xml中的典型配置和主要代码如下:
web.xml:

<filter>
<filter-name> CharacterEncodingFilter </filter-name>
<filter-class> net.vschool.web.CharacterEncodingFilter </filter-class>
<init-param>
<param-name> encoding </param-name>
<param-value> GBK </param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name> CharacterEncodingFilter </filter-name>
<url-pattern> /* </url-pattern>
</filter-mapping>

CharacterEncodingFilter.java:

public   class   CharacterEncodingFilter   implements   Filter  
{

protected   String   encoding   =   null;  

public   void   init(FilterConfig   filterConfig)   throws   ServletException  
{
this.encoding   =   filterConfig.getInitParameter( "encoding ");
}

public   void   doFilter(ServletRequest   request,   ServletResponse   response,   FilterChain   chain)   throws   IOException,   ServletException  
{
request.setCharacterEncoding(encoding);
response.setContentType( "text/html;charset= "+encoding);
chain.doFilter(request,   response);
}

}


2、Java与数据库之间的乱码
大 部分数据库都支持以unicode编码方式,所以解决Java与数据库之间的乱码问题比较明智的方式是直接使用unicode编码与数据库交互。很多数据 库驱动自动支持unicode,如Microsoft的SQLServer驱动。其他大部分数据库驱动,可以在驱动的url参数中指定,如如mm的 mysql驱动:jdbc:mysql://localhost/WEBCLDB?useUnicode=true& characterEncoding=GBK。

3、Java与文件/流之间的乱码
Java读写文件最常用的类是 FileInputStream/FileOutputStream和FileReader/FileWriter。其中FileInputStream 和FileOutputStream是基于字节流的,常用于读写二进制文件。读写字符文件建议使用基于字符的FileReader和 FileWriter,省去了字节与字符之间的转换。但这两个类的构造函数默认使用系统的编码方式,如果文件内容与系统编码方式不一致,可能会出现乱码。 在这种情况下,建议使用FileReader和FileWriter的父 类:InputStreamReader/OutputStreamWriter,它们也是基于字符的,但在构造函数中可以指定编码类 型:InputStreamReader(InputStream   in,   Charset   cs)   和OutputStreamWriter(OutputStream   out,   Charset   cs)。  

4、其他
上 面提到的方法应该能解决大部分乱码问题,如果在其他地方还出现乱码,可能需要手动修改代码。解决Java乱码问题的关键在于在字节与字符的转换过程中,你 必须知道原来字节或转换后的字节的编码方式,转换时采用的编码必须与这个编码方式保持一致。我们以前使用Resin服务器,使用smartUpload组 件上传文件,上传文件同时传递的中文参数获取没有乱码问题。当在Linux中把Resin设置成服务后,上传文件同时的中文参数获取出现了乱码。这个问题 困扰了我们很久,后来我们分析smartUpload组件的源文件,因为文件上传采用的是字节流的方式,里面包含的参数名称和值也是字节流的方式传递的。 smartUpload组件读取字节流后再将参数名称和值从字节流中解析出来,问题就出现在smartUpload将字节流转换成字符串时采用了系统默认 的编码,而将Resin设置成服务后,系统默认的编码可能发生了改变,因此出现了乱码。后来,我们更改了smartUpload的源文件,增加了一个属性 charset和setCharset(String)方法,将upload()方法中提取参数语句:
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1   );
改成了
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1,   charset   );
终于解决了这个乱码问题。
 
自从接触Java和JSP以来,就不断与Java的中文乱码问题打交道,现在终于得到了彻底的解决,现将我们的解决心得与大家共享。

一、Java中文问题的由来

Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面,Java和JSP文件本身编译时产生的乱码问题和Java程序于其他媒介交互产生的乱码问题。

首 先Java(包括JSP)源文件中很可能包含有中文,而Java和JSP源文件的保存方式是基于字节流的,如果Java和JSP编译成class文件过程 中,使用的编码方式与源文件的编码不一致,就会出现乱码。基于这种乱码,建议在Java文件中尽量不要写中文(注释部分不参与编译,写中文没关系),如果 必须写的话,尽量手动带参数-ecoding   GBK或-ecoding   gb2312编译;对于JSP,在文件头加上 <%@   page   contentType= "text/html;charset=GBK "%> 或 <%@   page   contentType= "text/html;charset=gb2312 "%> 基本上就能解决这类乱码问题。

本文要重点讨论的是第二类乱码,即Java程序与其他存储媒介交互时产生的乱码。很多存储媒介,如数据库,文件,流等的存储方式都是基于字节流的,Java程序与这些媒介交互时就会发生字符(char)与字节(byte)之间的转换,具体情况如下:

从页面form提交数据到java程序   byte-> char
从java程序到页面显示   char—> byte

从数据库到java程序   byte—> char
从java程序到数据库   char—> byte

从文件到java程序   byte-> char
从java程序到文件   char-> byte

从流到java程序   byte-> char
从java程序到流   char-> byte

如果在以上转换过程中使用的编码方式与字节原有的编码不一致,很可能就会出现乱码。

二、解决方法

前面已经提到了Java程序与其他媒介交互时字符和字节的转换过程,如果这些转换过程中容易产生乱码。解决这些乱码问题的关键在于确保转换时使用的编码方式与字节原有的编码方式保持一致,下面分别论述(Java或JSP自身产生的乱码请参看第一部分)。

1、JSP与页面参数之间的乱码
JSP 获取页面参数时一般采用系统默认的编码方式,如果页面参数的编码类型和系统默认的编码类型不一致,很可能就会出现乱码。解决这类乱码问题的基本方法是在页 面获取参数之前,强制指定request获取参数的编码方式:request.setCharacterEncoding( "GBK ")或request.setCharacterEncoding( "gb2312 ")。
如果在JSP将变量输出到页面时出现了乱码,可以 通过设置response.setContentType( "text/html;charset=GBK ")或response.setContentType( "text/html;charset=gb2312 ")解决。
如果不想在每个文件里都写这样两句话,更简洁的办法是使用Servlet规范中的过虑器指定编码,过滤器的在web.xml中的典型配置和主要代码如下:
web.xml:

<filter>
<filter-name> CharacterEncodingFilter </filter-name>
<filter-class> net.vschool.web.CharacterEncodingFilter </filter-class>
<init-param>
<param-name> encoding </param-name>
<param-value> GBK </param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name> CharacterEncodingFilter </filter-name>
<url-pattern> /* </url-pattern>
</filter-mapping>

CharacterEncodingFilter.java:

public   class   CharacterEncodingFilter   implements   Filter  
{

protected   String   encoding   =   null;  

public   void   init(FilterConfig   filterConfig)   throws   ServletException  
{
this.encoding   =   filterConfig.getInitParameter( "encoding ");
}

public   void   doFilter(ServletRequest   request,   ServletResponse   response,   FilterChain   chain)   throws   IOException,   ServletException  
{
request.setCharacterEncoding(encoding);
response.setContentType( "text/html;charset= "+encoding);
chain.doFilter(request,   response);
}

}


2、Java与数据库之间的乱码
大 部分数据库都支持以unicode编码方式,所以解决Java与数据库之间的乱码问题比较明智的方式是直接使用unicode编码与数据库交互。很多数据 库驱动自动支持unicode,如Microsoft的SQLServer驱动。其他大部分数据库驱动,可以在驱动的url参数中指定,如如mm的 mysql驱动:jdbc:mysql://localhost/WEBCLDB?useUnicode=true& characterEncoding=GBK。

3、Java与文件/流之间的乱码
Java读写文件最常用的类是 FileInputStream/FileOutputStream和FileReader/FileWriter。其中FileInputStream 和FileOutputStream是基于字节流的,常用于读写二进制文件。读写字符文件建议使用基于字符的FileReader和 FileWriter,省去了字节与字符之间的转换。但这两个类的构造函数默认使用系统的编码方式,如果文件内容与系统编码方式不一致,可能会出现乱码。 在这种情况下,建议使用FileReader和FileWriter的父 类:InputStreamReader/OutputStreamWriter,它们也是基于字符的,但在构造函数中可以指定编码类 型:InputStreamReader(InputStream   in,   Charset   cs)   和OutputStreamWriter(OutputStream   out,   Charset   cs)。  

4、其他
上 面提到的方法应该能解决大部分乱码问题,如果在其他地方还出现乱码,可能需要手动修改代码。解决Java乱码问题的关键在于在字节与字符的转换过程中,你 必须知道原来字节或转换后的字节的编码方式,转换时采用的编码必须与这个编码方式保持一致。我们以前使用Resin服务器,使用smartUpload组 件上传文件,上传文件同时传递的中文参数获取没有乱码问题。当在Linux中把Resin设置成服务后,上传文件同时的中文参数获取出现了乱码。这个问题 困扰了我们很久,后来我们分析smartUpload组件的源文件,因为文件上传采用的是字节流的方式,里面包含的参数名称和值也是字节流的方式传递的。 smartUpload组件读取字节流后再将参数名称和值从字节流中解析出来,问题就出现在smartUpload将字节流转换成字符串时采用了系统默认 的编码,而将Resin设置成服务后,系统默认的编码可能发生了改变,因此出现了乱码。后来,我们更改了smartUpload的源文件,增加了一个属性 charset和setCharset(String)方法,将upload()方法中提取参数语句:
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1   );
改成了
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1,   charset   );
终于解决了这个乱码问题。
 
自从接触Java和JSP以来,就不断与Java的中文乱码问题打交道,现在终于得到了彻底的解决,现将我们的解决心得与大家共享。

一、Java中文问题的由来

Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面,Java和JSP文件本身编译时产生的乱码问题和Java程序于其他媒介交互产生的乱码问题。

首 先Java(包括JSP)源文件中很可能包含有中文,而Java和JSP源文件的保存方式是基于字节流的,如果Java和JSP编译成class文件过程 中,使用的编码方式与源文件的编码不一致,就会出现乱码。基于这种乱码,建议在Java文件中尽量不要写中文(注释部分不参与编译,写中文没关系),如果 必须写的话,尽量手动带参数-ecoding   GBK或-ecoding   gb2312编译;对于JSP,在文件头加上 <%@   page   contentType= "text/html;charset=GBK "%> 或 <%@   page   contentType= "text/html;charset=gb2312 "%> 基本上就能解决这类乱码问题。

本文要重点讨论的是第二类乱码,即Java程序与其他存储媒介交互时产生的乱码。很多存储媒介,如数据库,文件,流等的存储方式都是基于字节流的,Java程序与这些媒介交互时就会发生字符(char)与字节(byte)之间的转换,具体情况如下:

从页面form提交数据到java程序   byte-> char
从java程序到页面显示   char—> byte

从数据库到java程序   byte—> char
从java程序到数据库   char—> byte

从文件到java程序   byte-> char
从java程序到文件   char-> byte

从流到java程序   byte-> char
从java程序到流   char-> byte

如果在以上转换过程中使用的编码方式与字节原有的编码不一致,很可能就会出现乱码。

二、解决方法

前面已经提到了Java程序与其他媒介交互时字符和字节的转换过程,如果这些转换过程中容易产生乱码。解决这些乱码问题的关键在于确保转换时使用的编码方式与字节原有的编码方式保持一致,下面分别论述(Java或JSP自身产生的乱码请参看第一部分)。

1、JSP与页面参数之间的乱码
JSP 获取页面参数时一般采用系统默认的编码方式,如果页面参数的编码类型和系统默认的编码类型不一致,很可能就会出现乱码。解决这类乱码问题的基本方法是在页 面获取参数之前,强制指定request获取参数的编码方式:request.setCharacterEncoding( "GBK ")或request.setCharacterEncoding( "gb2312 ")。
如果在JSP将变量输出到页面时出现了乱码,可以 通过设置response.setContentType( "text/html;charset=GBK ")或response.setContentType( "text/html;charset=gb2312 ")解决。
如果不想在每个文件里都写这样两句话,更简洁的办法是使用Servlet规范中的过虑器指定编码,过滤器的在web.xml中的典型配置和主要代码如下:
web.xml:

<filter>
<filter-name> CharacterEncodingFilter </filter-name>
<filter-class> net.vschool.web.CharacterEncodingFilter </filter-class>
<init-param>
<param-name> encoding </param-name>
<param-value> GBK </param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name> CharacterEncodingFilter </filter-name>
<url-pattern> /* </url-pattern>
</filter-mapping>

CharacterEncodingFilter.java:

public   class   CharacterEncodingFilter   implements   Filter  
{

protected   String   encoding   =   null;  

public   void   init(FilterConfig   filterConfig)   throws   ServletException  
{
this.encoding   =   filterConfig.getInitParameter( "encoding ");
}

public   void   doFilter(ServletRequest   request,   ServletResponse   response,   FilterChain   chain)   throws   IOException,   ServletException  
{
request.setCharacterEncoding(encoding);
response.setContentType( "text/html;charset= "+encoding);
chain.doFilter(request,   response);
}

}


2、Java与数据库之间的乱码
大 部分数据库都支持以unicode编码方式,所以解决Java与数据库之间的乱码问题比较明智的方式是直接使用unicode编码与数据库交互。很多数据 库驱动自动支持unicode,如Microsoft的SQLServer驱动。其他大部分数据库驱动,可以在驱动的url参数中指定,如如mm的 mysql驱动:jdbc:mysql://localhost/WEBCLDB?useUnicode=true& characterEncoding=GBK。

3、Java与文件/流之间的乱码
Java读写文件最常用的类是 FileInputStream/FileOutputStream和FileReader/FileWriter。其中FileInputStream 和FileOutputStream是基于字节流的,常用于读写二进制文件。读写字符文件建议使用基于字符的FileReader和 FileWriter,省去了字节与字符之间的转换。但这两个类的构造函数默认使用系统的编码方式,如果文件内容与系统编码方式不一致,可能会出现乱码。 在这种情况下,建议使用FileReader和FileWriter的父 类:InputStreamReader/OutputStreamWriter,它们也是基于字符的,但在构造函数中可以指定编码类 型:InputStreamReader(InputStream   in,   Charset   cs)   和OutputStreamWriter(OutputStream   out,   Charset   cs)。  

4、其他
上 面提到的方法应该能解决大部分乱码问题,如果在其他地方还出现乱码,可能需要手动修改代码。解决Java乱码问题的关键在于在字节与字符的转换过程中,你 必须知道原来字节或转换后的字节的编码方式,转换时采用的编码必须与这个编码方式保持一致。我们以前使用Resin服务器,使用smartUpload组 件上传文件,上传文件同时传递的中文参数获取没有乱码问题。当在Linux中把Resin设置成服务后,上传文件同时的中文参数获取出现了乱码。这个问题 困扰了我们很久,后来我们分析smartUpload组件的源文件,因为文件上传采用的是字节流的方式,里面包含的参数名称和值也是字节流的方式传递的。 smartUpload组件读取字节流后再将参数名称和值从字节流中解析出来,问题就出现在smartUpload将字节流转换成字符串时采用了系统默认 的编码,而将Resin设置成服务后,系统默认的编码可能发生了改变,因此出现了乱码。后来,我们更改了smartUpload的源文件,增加了一个属性 charset和setCharset(String)方法,将upload()方法中提取参数语句:
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1   );
改成了
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1,   charset   );
终于解决了这个乱码问题。

 

自从接触Java和JSP以来,就不断与Java的中文乱码问题打交道,现在终于得到了彻底的解决,现将我们的解决心得与大家共享。

一、Java中文问题的由来

Java的内核和class文件是基于unicode的,这使Java程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面,Java和JSP文件本身编译时产生的乱码问题和Java程序于其他媒介交互产生的乱码问题。

首 先Java(包括JSP)源文件中很可能包含有中文,而Java和JSP源文件的保存方式是基于字节流的,如果Java和JSP编译成class文件过程 中,使用的编码方式与源文件的编码不一致,就会出现乱码。基于这种乱码,建议在Java文件中尽量不要写中文(注释部分不参与编译,写中文没关系),如果 必须写的话,尽量手动带参数-ecoding   GBK或-ecoding   gb2312编译;对于JSP,在文件头加上 <%@   page   contentType= "text/html;charset=GBK "%> 或 <%@   page   contentType= "text/html;charset=gb2312 "%> 基本上就能解决这类乱码问题。

本文要重点讨论的是第二类乱码,即Java程序与其他存储媒介交互时产生的乱码。很多存储媒介,如数据库,文件,流等的存储方式都是基于字节流的,Java程序与这些媒介交互时就会发生字符(char)与字节(byte)之间的转换,具体情况如下:

从页面form提交数据到java程序   byte-> char
从java程序到页面显示   char—> byte

从数据库到java程序   byte—> char
从java程序到数据库   char—> byte

从文件到java程序   byte-> char
从java程序到文件   char-> byte

从流到java程序   byte-> char
从java程序到流   char-> byte

如果在以上转换过程中使用的编码方式与字节原有的编码不一致,很可能就会出现乱码。

二、解决方法

前面已经提到了Java程序与其他媒介交互时字符和字节的转换过程,如果这些转换过程中容易产生乱码。解决这些乱码问题的关键在于确保转换时使用的编码方式与字节原有的编码方式保持一致,下面分别论述(Java或JSP自身产生的乱码请参看第一部分)。

1、JSP与页面参数之间的乱码
JSP 获取页面参数时一般采用系统默认的编码方式,如果页面参数的编码类型和系统默认的编码类型不一致,很可能就会出现乱码。解决这类乱码问题的基本方法是在页 面获取参数之前,强制指定request获取参数的编码方式:request.setCharacterEncoding( "GBK ")或request.setCharacterEncoding( "gb2312 ")。
如果在JSP将变量输出到页面时出现了乱码,可以 通过设置response.setContentType( "text/html;charset=GBK ")或response.setContentType( "text/html;charset=gb2312 ")解决。
如果不想在每个文件里都写这样两句话,更简洁的办法是使用Servlet规范中的过虑器指定编码,过滤器的在web.xml中的典型配置和主要代码如下:
web.xml:

<filter>
<filter-name> CharacterEncodingFilter </filter-name>
<filter-class> net.vschool.web.CharacterEncodingFilter </filter-class>
<init-param>
<param-name> encoding </param-name>
<param-value> GBK </param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name> CharacterEncodingFilter </filter-name>
<url-pattern> /* </url-pattern>
</filter-mapping>

CharacterEncodingFilter.java:

public   class   CharacterEncodingFilter   implements   Filter  
{

protected   String   encoding   =   null;  

public   void   init(FilterConfig   filterConfig)   throws   ServletException  
{
this.encoding   =   filterConfig.getInitParameter( "encoding ");
}

public   void   doFilter(ServletRequest   request,   ServletResponse   response,   FilterChain   chain)   throws   IOException,   ServletException  
{
request.setCharacterEncoding(encoding);
response.setContentType( "text/html;charset= "+encoding);
chain.doFilter(request,   response);
}

}


2、Java与数据库之间的乱码
大 部分数据库都支持以unicode编码方式,所以解决Java与数据库之间的乱码问题比较明智的方式是直接使用unicode编码与数据库交互。很多数据 库驱动自动支持unicode,如Microsoft的SQLServer驱动。其他大部分数据库驱动,可以在驱动的url参数中指定,如如mm的 mysql驱动:jdbc:mysql://localhost/WEBCLDB?useUnicode=true& characterEncoding=GBK。

3、Java与文件/流之间的乱码
Java读写文件最常用的类是 FileInputStream/FileOutputStream和FileReader/FileWriter。其中FileInputStream 和FileOutputStream是基于字节流的,常用于读写二进制文件。读写字符文件建议使用基于字符的FileReader和 FileWriter,省去了字节与字符之间的转换。但这两个类的构造函数默认使用系统的编码方式,如果文件内容与系统编码方式不一致,可能会出现乱码。 在这种情况下,建议使用FileReader和FileWriter的父 类:InputStreamReader/OutputStreamWriter,它们也是基于字符的,但在构造函数中可以指定编码类 型:InputStreamReader(InputStream   in,   Charset   cs)   和OutputStreamWriter(OutputStream   out,   Charset   cs)。  

4、其他
上 面提到的方法应该能解决大部分乱码问题,如果在其他地方还出现乱码,可能需要手动修改代码。解决Java乱码问题的关键在于在字节与字符的转换过程中,你 必须知道原来字节或转换后的字节的编码方式,转换时采用的编码必须与这个编码方式保持一致。我们以前使用Resin服务器,使用smartUpload组 件上传文件,上传文件同时传递的中文参数获取没有乱码问题。当在Linux中把Resin设置成服务后,上传文件同时的中文参数获取出现了乱码。这个问题 困扰了我们很久,后来我们分析smartUpload组件的源文件,因为文件上传采用的是字节流的方式,里面包含的参数名称和值也是字节流的方式传递的。 smartUpload组件读取字节流后再将参数名称和值从字节流中解析出来,问题就出现在smartUpload将字节流转换成字符串时采用了系统默认 的编码,而将Resin设置成服务后,系统默认的编码可能发生了改变,因此出现了乱码。后来,我们更改了smartUpload的源文件,增加了一个属性 charset和setCharset(String)方法,将upload()方法中提取参数语句:
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1   );
改成了
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1,   charset   );
终于解决了这个乱码问题。

自从接触 JavaJSP 以来,就不断与 Java 的中文乱码问题打交道,现在终于得到了彻底的解决,现将我们的解决心得与大家共享。

一、 Java 中文问题的由来

Java
的内核和 class 文件是基于 unicode 的,这使 Java 程序具有良好的跨平台性,但也带来了一些中文乱码问题的麻烦。原因主要有两方面, JavaJSP 文件本身编译时产生的乱码问题和 Java 程序于其他媒介交互产生的乱码问题。

首先 Java (包括 JSP )源文件中很可能包含有中文,而 JavaJSP 源文件的保存方式是基于字节流的,如果 JavaJSP 编译成 class 文件过程中,使用的编码方式与源文件的编码不一致,就会出现乱码。基于这种乱码,建议在 Java 文件中尽量不要写中文(注释部分不参与编译,写中文没关系),如果必须写的话,尽量手动带参数- ecoding   GBK 或- ecoding   gb2312 编译;对于 JSP ,在文件头加上 <%@   page   contentType= "text/html;charset=GBK "%> <%@   page   contentType= "text/html;charset=gb2312 "%> 基本上就能解决这类乱码问题。

本文要重点讨论的是第二类乱码,即 Java 程序与其他存储媒介交互时产生的乱码。很多存储媒介,如数据库,文件,流等的存储方式都是基于字节流的, Java 程序与这些媒介交互时就会发生字符 (char) 与字节 (byte) 之间的转换,具体情况如下:

从页面 form 提交数据到 java 程序   byte> char
java 程序到页面显示   char—> byte

从数据库到 java 程序   byte—> char
java 程序到数据库   char—> byte

从文件到 java 程序   byte> char
java 程序到文件   char> byte

从流到 java 程序   byte> char
java 程序到流   char> byte

如果在以上转换过程中使用的编码方式与字节原有的编码不一致,很可能就会出现乱码。

二、解决方法

前面已经提到了 Java 程序与其他媒介交互时字符和字节的转换过程,如果这些转换过程中容易产生乱码。解决这些乱码问题的关键在于确保转换时使用的编码方式与字节原有的编码方式保持一致,下面分别论述( JavaJSP 自身产生的乱码请参看第一部分)。

1
JSP 与页面参数之间的乱码
JSP
获取页面参数时一般采用系统默认的编码方式,如果页面参数的编码类型和系统默认的编码类型不一致,很可能就会出现乱码。解决这类乱码问题的基本方法是在页面获取参数之前,强制指定 request 获取参数的编码方式: request.setCharacterEncoding( "GBK ")request.setCharacterEncoding( "gb2312 ")
如果在 JSP 将变量输出到页面时出现了乱码,可以通过设置 response.setContentType( "text/html;charset=GBK ")response.setContentType( "text/html;charset=gb2312 ") 解决。
如果不想在每个文件里都写这样两句话,更简洁的办法是使用 Servlet 规范中的过虑器指定编码,过滤器的在 web.xml 中的典型配置和主要代码如下:
web.xml:

<filter>
<filter-name> CharacterEncodingFilter </filter-name>
<filter-class> net.vschool.web.CharacterEncodingFilter </filter-class>
<init-param>
<param-name> encoding </param-name>
<param-value> GBK </param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name> CharacterEncodingFilter </filter-name>
<url-pattern> /* </url-pattern>
</filter-mapping>

CharacterEncodingFilter.java:

public   class   CharacterEncodingFilter   implements   Filter  
{

protected   String   encoding   =   null;  

public   void   init(FilterConfig   filterConfig)   throws   ServletException  
{
this.encoding   =   filterConfig.getInitParameter( "encoding ");
}

public   void   doFilter(ServletRequest   request,   ServletResponse   response,   FilterChain   chain)   throws   IOException,   ServletException  
{
request.setCharacterEncoding(encoding);
response.setContentType( "text/html;charset= "+encoding);
chain.doFilter(request,   response);
}

}


2
Java 与数据库之间的乱码
大部分数据库都支持以 unicode 编码方式,所以解决 Java 与数据库之间的乱码问题比较明智的方式是直接使用 unicode 编码与数据库交互。很多数据库驱动自动支持 unicode ,如 MicrosoftSQLServer 驱动。其他大部分数据库驱动,可以在驱动的 url 参数中指定,如如 mmmysql 驱动: jdbc:mysql://localhost/WEBCLDB?useUnicode=true&characterEncoding=GBK

3
Java 与文件 / 流之间的乱码
Java
读写文件最常用的类是 FileInputStream/FileOutputStreamFileReader/FileWriter 。其中 FileInputStreamFileOutputStream 是基于字节流的,常用于读写二进制文件。读写字符文件建议使用基于字符的 FileReaderFileWriter ,省去了字节与字符之间的转换。但这两个类的构造函数默认使用系统的编码方式,如果文件内容与系统编码方式不一致,可能会出现乱码。在这种情况下,建议使用 FileReaderFileWriter 的父类: InputStreamReader/OutputStreamWriter ,它们也是基于字符的,但在构造函数中可以指定编码类型: InputStreamReader(InputStream   in,   Charset   cs)   OutputStreamWriter(OutputStream   out,   Charset   cs)  

4
、其他
上面提到的方法应该能解决大部分乱码问题,如果在其他地方还出现乱码,可能需要手动修改代码。解决 Java 乱码问题的关键在于在字节与字符的转换过程中,你必须知道原来字节或转换后的字节的编码方式,转换时采用的编码必须与这个编码方式保持一致。我们以前使用 Resin 服务器,使用 smartUpload 组件上传文件,上传文件同时传递的中文参数获取没有乱码问题。当在 Linux 中把 Resin 设置成服务后,上传文件同时的中文参数获取出现了乱码。这个问题困扰了我们很久,后来我们分析 smartUpload 组件的源文件,因为文件上传采用的是字节流的方式,里面包含的参数名称和值也是字节流的方式传递的。 smartUpload 组件读取字节流后再将参数名称和值从字节流中解析出来,问题就出现在 smartUpload 将字节流转换成字符串时采用了系统默认的编码,而将 Resin 设置成服务后,系统默认的编码可能发生了改变,因此出现了乱码。后来,我们更改了 smartUpload 的源文件,增加了一个属性 charsetsetCharset(String) 方法,将 upload() 方法中提取参数语句:
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1   );
改成了
String   value   =   new   String(m_binArray,   m_startData,   (m_endData   -   m_startData)   +   1,   charset   );
终于解决了这个乱码问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值