java的GET和POST中文乱码原因和解决方法

3  Java语言中产生乱码的原因及解决方法

3.1基于awt(swing)的图形界面程序中文显示乱码

基 于awt(swing)的图形界面程序中,一般会出现菜单中的中文显示乱码,其原因一般是JVM找不到用来显示中文的字库,JVM在原始的安装下是没有中 文字库的,而linux的发行版本又各不相同,其字库存放的路径和名字又各不相同,所以JVM一般是找不到linux操作系统内带的字库,解决方法是让 JVM能找到linux操作系统内带的字库,如在Redflag 6.0下可以通过下面命令解决:

mkdir /usr/java/jdk1.6.0/jre/lib/fonts/fallback

ln -s /usr/share/fonts/chinese/TrueType/*.ttf /usr/java/jdk1.6.0/jre/lib/fonts/fallback

一般不需要修改JRE/lib/目录下的字体配置文件(fontconfig.OS.Version.properties)。

3.2 基于B/S结构的JSP(Servlet)的系统用户端浏览器中文显示乱码

3.2.1页面中的中文显示乱码

对于像HTML的静态文件,其文件的字符集只要和文件中<meta http-equiv="Content-Type" content="text/html; charset=…… ">处所设置的一样即可。

对 于像JSP和Servlet动态文件由于需要经过编译,在运行是由JVM解释class文件而产生用户端浏览器所需的HTML文件,如果产生中文乱码,则 一般是由编译和运行过程中产生的。如果用商用的发行版Linux和服务器,一般只要将JSP或Servlet文件保存为UTF-8字符集, 将<meta http-equiv = "Content-Type" content="text/html; charset=…… ">中设置为UTF-8即可。如果还出现乱码则可以通过以下方法解决:

①如果服务器是自主研发的,可以通过修改源代码,指定 JVM读文件、写文件以及生成用户端浏览器所需的HTML文件时,字符串与二进制序列流转换时的编码方式,从而从根本上解决问题,增强服务器的适应性,在 MyWebServer 2.0中,我就采用了这种方法,代码如下:

new BufferedReader(new InputStreamReader(new FileInputStream(jspfile),"GBK"));

new PrintWriter(serfile,"GBK");

new PrintWriter(new OutputStreamWriter(os,"GBK"));

②当然也可以在服务器的入口文件(即含有main子函数的文件)中修改JVM的“locale”设置,代码如下:

Locale.setDefault(new Locale(“zh”,”CN”));

③当采用商用服务器时,可以修改启动服务器的shell文件,在启动服务器前设置环境变量“export LC_ALL=zh_CN.UTF-8”,从而改变本控制台下默认的“locale”值。

④当然也可以修改操作系统的“locale”设置,但由于修改操作系统的“locale”设置将会影响到其他应用程序,所以一般采用该方法。

采 用上述方法的主要原因是,当JVM在首次起动时,将会把操作系统的“locale”设置为JVM的默认“locale”,在操作系统没有设置 “locale”值时(如mylinux 1.0),JVM将会把JVM的缺省的“locale”设置为JVM的默认“locale”,当然也可以在运行应用程序时修改JVM的默认 “locale”设置,在JVM进行字符串与二进制序列流相互转换时,如果指定了编码方式,将以指定的编码方式转换,否则根据JVM的默认 “locale”进行转换。

3.2.2 get方法从URL获取的参数中中文显示乱码

     对于get方法来说,都是把数据串联在请求的url后面作为参数,url拼接完成后,浏览器会对url进行URL encode,然后发送给服务器,URL encode的过程就是把部分的url做为字符,按照某种编码方式(如:utf-8,gbk等)编码成二进制的字节码,然后每个字节用一个包含3个字符的 字符串 "%xy" 表示,其中xy为该字节的两位十六进制表示形式。了解了URL encode的过程,我们能看到2个很重要的问题,第一:需要URL encode的字符一般都是非ASCII的字符,所以都是英文字母的url不会出现服务器得到乱码问题,出现乱码都是url里面带了中文或特殊字符造成 的;第二:URL encode到底按照那种编码方式对字符编码?不同的浏览器有不同的做法,中文版的浏览器一般会默认的使用GBK,通过设置浏览器也可以使用UTF-8, 完成了URL encode的url就成了ASCII范围内的字符了,然后以iso-8859-1的编码方式转换成二进制随着请求头一起发送出去。

服 务器端获取到数据,第一步是先把数据用iso-8859-1进行解码,对于get方法来说,tomcat获取数据的是ASCII范围内的请求头字符,其中 的请求url里面带有参数数据,如果参数中有中文等特殊字符,那么目前还是URL encode后的%XY状态,先停下,我们先说下开发人员一般获取数据的过程。通常大家都是request.getParameter("name")获 取参数数据,我们在request对象或得的数据都是经过解码过的,而解码过程中程序里是无法指定,服务器tomcat默认缺省用的是iso- 8859-1,这样我们就能找到为什么get请求带中文参数为什么在服务器端得到乱码了,原因是在客户端一般都是用UTF-8或GBK对数据URL encode,这里用iso-8859-1方式URL decoder显然不行,所以一般可以采用以下代码解决:

String Sname = new String(request.getParameter("name").getBytes("iso-8859-1"),"GBK");

//其中的“GBK”为用户端用浏览器URL编码方式。

也可以修改服务器的配置文件,让服务器在获取数据后用指定的方式进行URL decoder。

如 果服务器是自主研发的,可以通过修改服务器的源代码,指定URL的解编码方式,从而解决问题。如在myWebServer2.0中,我采用了在程序中直接 指定以"iso-8859-1"字符集组装二进制序列流,用“GBK“进行URL的解编码,从而可以使在众多的微软中文IE浏览器下JSP可以直接接收到 正确的中文参数。相关代码如下:

InputStreamReader myISR=new InputStreamReader(in,"iso-8859-1");

temp=URLDecoder.decode(temp,"GBK");

然 而在做开发时,不可能要求用户端用浏览器都用同样的方式进行URL编码,为了服务器能正确接收所有的用户的URL中的中文参数,通常可以通过用 JavaScript角本语言先将参数进行编码,编码后参数中的中文将会转换为”ACSII”码,然后再拼装到URL的后面提交,这时在服务器端就可以用 统一的方式从request中取到URL,然后再取出URL的参数进行解码。

3.2.3  post方法提交的中文参数出现乱码

在 post方法里所要传送的数据也要URL编码,在form所在的html文件里如果有段<meta http-equiv="Content-Type" content="text/html; charset=gb2312 "/>,那么post就会用此处指定的编码方式编码。一般大家都认为这段代码是为了让浏览器知道用什么字符集来对网页解释,其实它还有个作用就是指 定form表单的post方法提交数据的URL encode编码方式。对于get方法来数,浏览器对数据的URL encode的编码方式是有浏览器设置来决定,而post方法,开发人员可以指定。如果用tomcat默认缺省设置,也没做过滤器等编码设置,那么他也是 用“iso-8859-1”解码的,也可以通过在JSP中设置request.setCharacterEncoding("…")这时服务器会以JSP 中指定的字符集解码。

4  结论

Java语言在linux下中文显示产生的乱码,主要与JVM的字库、操作系统的 locale设置、JVM的默认locale设置、应用程序中的locale设置以及应用程序中直接指定的二进制序列流与字符串转化的字符集有关。是由于 二进制序列流和字符串相互转化过程中所采用的字符编码方式不同或者JVM找不到所需要的字库所致,可以采取不同的方法去解决,具体采用哪种方法处理还要结 合具体的应用环境。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值