解决中文乱码问题

软件和网站开发以及相关技术探讨
回复
nbsven
帖子: 2
注册时间: 2009-04-27 12:20

解决中文乱码问题

#1

帖子 nbsven » 2009-05-18 15:20

在基于JAVA的编程中,经常会碰到汉字的处里及显示的问题,比如一大堆乱码或问号。这是因为JAVA中默认的编码方式是UNICODE,而中国人通常使用的文件和DB都是基于GB2312或者BIG5等编码,故会出现此问题。本文抽取了UFO中的演示实例来介绍如何解决中文乱码问题, UFO是www.gm365.com发布的一个web server软件(以建设网站的稳定性和高负载能力,快速的响应速度和低CPU消耗的功能而开发)。

1、解决jsp中文乱码问题
在jsp中,当使用out.print(request.getParameter("parameter-name"))输出表单数据时,如果表单数据为中文字符时,则输出的内容是乱码。引起中文乱码的原因是,在默认情况下,提取表单数据使用的编码格式为UTF-8.为了解决中文乱码问题,首先要使用 ISO-8859-1 编码格式将表单数据存储到字节数组中,然后再使用借助 gb2312的编码格式将字节数组转换为字符串。完整的处理表单的程序代码如下:

例如:我们要将用户提交的表单数据输入到页面,直接用如下方法将会在parameter-name为中文字符时出现乱码
<%
String pName =request.getParameter("parameter-name");
out.println(pName);
%>
需要对其做如下改动可解决此类中文字符乱码问题:
<%
String pName =request.getParameter("parameter-name");
byte[] bytesStr=pName.getBytes("ISO-8859-1");
out.println(new String(bytesStr,"gb2312"));
%>

2、如何处理servlet中的中文字符乱码问题(以jsp文件调用servlet为例来演示如何处理中文字符)

ioFileServlet.jsp (此jsp文件用来写入文件、提交给servlet文件ioFileServlet来处理)

<%@ page contentType="text/html;charset=GB2312" %>
<script language="javascript">
function on_submit()
{//验证数据的合法性
if (form1.file_content.value == "")
{
alert("文件内容不能为空,请输入文件内容!");
form1.file_content.focus();
return false;
}
}
</script>
<HTML>
<head>
<title>提交文件内容</title>
</head>
<BODY>
<div align="center">
<center>
<table border="1">
<tr><td colspan="2" align="center">用servlet处理输入的文件内容</td></tr>
<tr>
<tr><td>
<form name="form1" action="servlet/readdata/ioFileServlet" method="post" onsubmit="return on_submit()">
请输入文件内容:
</td><td>
<textarea rows="7" name="file_content" cols="52"></textarea>
</td></tr>
<tr><td colspan="2" align="center"><input type="submit" value="提交"></td></tr>
</form>
</table>
</center>
</div>
</html>

servlet文件ioFileServlet的源代码:
ioFileServlet.java

package readdata;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
public class ioFileServlet extends HttpServlet
{
public String codeToString(String str)
{//处理中文字符串的函数
String s=str;
try
{
byte tempB[]=s.getBytes("ISO-8859-1");
s=new String(tempB);
return s;
}
catch(Exception e)
{
return s;
}
}
public void init(ServletConfig config) throws ServletException
{
super.init(config);
}
public void doPost(HttpServletRequest request,HttpServletResponse response)
throws ServletException,IOException
{
//设置mime
response.setContentType("text/html;charset=GB2312");
PrintWriter out=response.getWriter();
out.println("<HTML><head><title>接收新用户注册</title></head><BODY>");
//把提交的文件内容写入文件
int RowSize=30;//文件每行的字符数
String tempString1=null;
String tempString2=null;
tempString1=codeToString(request.getParameter("file_content"));
if(tempString1!=null)
{
File tempFile1=new File("d:/fileContent.txt");
FileWriter outfile1=new FileWriter(tempFile1,true);
BufferedWriter outbuffer1=new BufferedWriter(outfile1);
int writeStringLength=tempString1.length();
for(int i=0;i<writeStringLength/RowSize+1;i++)
{
if((i+1)*20<writeStringLength)
{
tempString2=tempString1.substring(i*RowSize,(i+1)*RowSize);
}
else
{
tempString2=tempString1.substring(i*RowSize,writeStringLength);
}
outbuffer1.write(tempString2);
outbuffer1.newLine();
}
outbuffer1.flush();
outbuffer1.close();
outfile1.close();
}
out.println("写入的文件内容是:<br>");
//从文件中读取内容
File f=new File("d:/fileContent.txt");
if(f.exists())
{
FileReader fileReader1=new FileReader(f);
BufferedReader buffer1=new BufferedReader(fileReader1);
byte bufferArray[]=new byte[90];
String tempString=null;
while((tempString=buffer1.readLine())!=null)
{
out.println(tempString+"<br>");
}
buffer1.close();
fileReader1.close();
}
else
{
out.println("故事中暂时没有内容。");
}
out.println("</body> </html>");
}
}

servlet功能用来接受ioFileServlet.jsp页面写入的内容、将其存入d盘根目录中的fileContent.txt中(如果没有就新建),最后将写入到fileContent.txt文件的所有内容显示出来。去掉servle处理中文字符串的函数、即不对servlet中的中文字符串进行处理,写入文件的内容将显示乱码。
头像
xieshaohu
帖子: 1565
注册时间: 2007-10-24 20:20
来自: 北京、海淀
联系:

Re: 解决中文乱码问题

#2

帖子 xieshaohu » 2009-05-19 8:04

关于Servlet和JSP,楼主怎么没有用到过滤器呢?

直接过滤器处理一下编码集不就OK了。
Dell Vostro 1500, T7300/4GB/WD5000BEVT/nVidia 8400GM, Ubuntu 10.04 x86_64/VMware 7(Win7)
我的博客:http://xieshaohu.wordpress.com/
头像
lululau
帖子: 105
注册时间: 2007-05-28 11:17

Re: 解决中文乱码问题

#3

帖子 lululau » 2009-05-29 12:52

表单数据的编码方式是由表单所在的页面的编码方式决定的,这有两种情况:
1、由<meta http-equiv="Content_Type" content="text/html; charset=XXX">
2、由该页面返回时的HTTP头信息决定。对于JSP来说,HTTP头信息由
<%@ page pageEncoding="XXX" contentType="XXX" %>决定,
这对应于Servlet的response.setContetnType("XXX");
默认情况下,服务器对提交上来的表单数据按照"latin1(ISO8859-1)"进行字符提取
这也就是为什么我们需要先用String.getBytes("ISO-8859-1")对获取的数据进行解码的原因了。
解码之后,当然就是再按照正确的编码方式对解码所得的字节数组重新进行编码( new String(byte[] buf, "XXX") ),
这个所谓的正确的编码方式也就是表单所在的那个页面的编码方式。
当然还有另外一种简单的方法就是:
在提取表单数据之前先设置编码:request.setCharacterEncoding("XXX");
这就是2楼说的,通常是使用一个过滤器,来调用request.setCharacterEncoding("XXX");,设置编码。

另,下面是一点关于<%@page%>JSP命令的pageEncoding和contentType属性的一点认识:
1. pageEncoding是供JSP容器读取, 用以容器识别JSP文件的编码。所以它的值必须和文件的实际编码一致。

2. Eclipse会判断用户所编写的JSP文件的这个属性的值,然后按照这个值对用户的JSP文件进行编码存盘。所以当你将pageEncoding的值设置为JAVA不支持的字符集时,这个JSP文件在Eclipse中是根本无法保存的。

(综合这两条,你会发现,当你使用Eclipse来写JSP时,只要你在JSP中设置是有效的编码,那么Tomcat就绝对不会把UTF-8的JSP文件当成latin1来翻译。)

3. contentType: 这个属性最终将会被翻译成这样一句话:response.setContentType("XXX"); 对于JSP(MIME类型是text/html)来说,这句话的作用是将页面数据按照value中指定的字符集进行编码,然后传给客户端,并告知客户端网络字节流所采用的编码格式。

4. 当pageEncoding和contentType只设置了一个的时候,JSP容器会自动将另一个属性也按照已设置的那个属性的值进行处理。并且当你只设置了contentType时,Eclipse也会按照contentType的值对JSP文件进行编码存盘。
回复