一.Java中的编码和中文问题
从 Java 源代码到得到正确的结果,要经过 “Java 源代码-> Java 字节码-> ;虚拟机->操作系统->显示设备”的过程。在上述过程中的每一步骤,我们都必须正确地处理汉字的编码,才能够使最终的显示结果正确。
Java 源代码-> Java 字节码 在编译的时候添加encoding参数,这样才能够与平台无关.
Java 字节码->虚拟机->操作系统 Java 运行环境 (JRE) 分英文版和国际版,但只有国际版才支持非英文字符。 Java 开发工具包 (JDK) 肯定支持多国字符,但并非所有的计算机用户都安装了 JDK 。很多操作系统及应用软件为了能够更好的支持 Java ,都内嵌了 JRE 的国际版本,为自己支持多国字符提供了方便。
操作系统->显示设备 对于汉字来说,操作系统必须支持并能够显示它。英文操作系统如果不搭配特殊的应用软件的话,是肯定不能够显示中文的。
在java编译过程中,对中文字符进行正确的编码转换,在使用out.println(string);或者<%=string%>时候,都必须作unicode到GBK的转换.
在jsp中的使用是<%@page contentType=”text/html;charset=gb2312” %>
在没有提供对输出字符的支持时,可以使用:
String s1 = request.getParameter(“keyword”);
String s2 = new String(s1.getBytes(“ISO-8859-1”),”GBK”);
getBytes 方法用于将中文字符以“ISO-8859-1”编码方式转化成字节数组,而“GBK” 是目标编码方式。
个人理解:
在JSP中Encoding和Charset的区别:
encoding指的是JSP中的<% %>编译为.class文件时所使用的编码.指的是输入到编译成类文件的时候所转化进行的编码.(理解为输入时的转化编码)
Charset 指的是向网页中输出的时候所进行的编码转换,作用是当要使用<%=string %>的时候所使用(理解为输出时的转化编码)
两者区别:encoding是做隐式的文件转化编码,charset是作显示的转化作用与显示.
将 GB2312 文件转换成 Big5 文件
import java.io.*;
import java.util.*;
public class gb2big5
{
static int iCharNum=0;
public static void main(String[] args) {
System.out.println("Input GB2312 file, output Big5 file.");
if (args.length!=2)
{
System.err.println("Usage: jview gb2big5 gbfile big5file");
System.exit(1);
String inputString = readInput(args[0]);
writeOutput(inputString,args[1]);
System.out.println("Number of Characters in file: "+iCharNum+".");
}
static void writeOutput(String str, String strOutFile)
{
try
{
FileOutputStream fos = new FileOutputStream(strOutFile);
Writer out = new OutputStreamWriter(fos, "Big5");
out.write(str);
out.close();
}
catch (IOException e)
{
e.printStackTrace();
e.printStackTrace();
}
}
static String readInput(String strInFile)
{
StringBuffer buffer = new StringBuffer();
try
{
FileInputStream fis = new FileInputStream(strInFile);
InputStreamReader isr = new InputStreamReader(fis, "GB2312");
Reader in = new BufferedReader(isr);
int ch;
while ((ch = in.read()) > -1)
{
iCharNum += 1;buffer.append((char)ch);
}
in.close();
return buffer.toString();
}
catch (IOException e)
{
e.printStackTrace();
return null;
}
}
}
二.JSP中的pageEncoding和contentType属性区别
关于JSP页面中的pageEncoding和contentType两种属性的区别:
pageEncoding是jsp文件本身的编码
contentType的charset是指服务器发送给客户端时的内容编码
JSP要经过两次的“编码”,第一阶段会用pageEncoding,第二阶段会用utf-8至utf-8,第三阶段就是由Tomcat出来的网页, 用的是contentType。
第一阶段是jsp编译成.java,它会根据pageEncoding的设定读取jsp,结果是由指定的编码方案翻译成统一的UTF-8 JAVA源码(即.java),如果pageEncoding设定错了,或没有设定,出来的就是中文乱码。
第二阶段是由JAVAC的JAVA源码至java byteCode的编译,不论JSP编写时候用的是什么编码方案,经过这个阶段的结果全部是UTF-8的encoding的java源码。
JAVAC用UTF-8的encoding读取java源码,编译成UTF-8 encoding的二进制码(即.class),这是JVM对常数字串在二进制码(java encoding)内表达的规范。
第三阶段是Tomcat(或其的application container)载入和执行阶段二的来的JAVA二进制码,输出的结果,也就是在客户端见到的,这时隐藏在阶段一和阶段二的参数contentType就发挥了功效
contentType的設定.
pageEncoding 和contentType的预设都是 ISO8859-1. 而随便设定了其中一个, 另一个就跟着一样了(TOMCAT4.1.27是如此). 但这不是绝对的, 这要看各自JSPC的处理方式. 而pageEncoding不等于contentType, 更有利亚洲区的文字 CJKV系JSP网页的开发和展示, (例pageEncoding=GB2312 不等于 contentType=utf-8)。
jsp文件不像.java,.java在被编译器读入的时候默认采用的是操作系统所设定的locale所对应的编码,比如中国大陆就是GBK,台湾就是BIG5或者MS950。而一般我们不管是在记事本还是在ue中写代码,如果没有经过特别转码的话,写出来的都是本地编码格式的内容。所以编译器采用的方法刚好可以让虚拟机得到正确的资料。
但是jsp文件不是这样,它没有这个默认转码过程,但是指定了pageEncoding就可以实现正确转码了。
举个例子:
<%@ page contentType="text/html;charset=utf-8" %>
大都会打印出乱码,因为输入的“你好”是gbk的,但是服务器是否正确抓到“你好”不得而知。
但是如果更改为
<%@ page contentType="text/html;charset=utf-8" pageEncoding="GBK"%>
这样就服务器一定会是正确抓到“你好”了。
三.网页乱码 UTF-8与GB2312 及 JSP中文问题
研究好多天了,也试过好多办法了,总结出目前发现最好的方法:
先说一下基本的东西:
<%@ codepage=936%>简体中文
<%@ codepage=950%>繁体中文
<%@ codepage=65001%>UTF-8
codepage指定了IIS按什么编码读取传递过来的串串(表单提交,地址栏传递等)。
出乱码的原因也就是网站要整合的时候模块编码不一样引起的。
就像我的博客一样,整合的时候都会出这个问题,因为BLOG是Utf-8的,
近来很多网友都在为这个问题咨询,我尝试了很多种方法。
最方便的方法如下:
不要转换任何模块网页的编码该utf-8的还是utf-8,该Gb22312的还是Gb2312
在Utf-8模块的包文件(如conn.asp,但是要注意conn.asp必须是在第一行调用)最前面加上
<%@LANGUAGE="VBSCRIPT" CODEPAGE="65001"%>
<%Session.CodePage=65001%>
在GB2312模块的包文件最前面加上
<%@LANGUAGE="VBSCRIPT" CODEPAGE="936"%>
<%Session.CodePage=936%>
其他编码的类推。再出问题,我也帮你了了,我现在是都没问题了^^
JSP中文问题
大家在JSP的开发过程中,经常出现中文乱码的问题,可能一至困扰着您,我现在把我在JSP开发中遇到的中文乱码的问题及解决办法写出来供大家参考。
1、JSP页面显示乱码
下面的显示页面(display.jsp)就出现乱码:
<html>
<head>
<title>JSP的中文处理</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<%
out.print("JSP的中文处理");
%>
</body>
</html>
(这里等同与将charset设置成默认的ISO-8859-1编码了)
对不同的WEB服务器和不同的JDK版本,处理结果就不一样。原因:服务器使用的编码方式不同和浏览器对不同的字符显示结果不同而导致的。解决办法:在JSP页面中指定编码方式(gb2312),即在页面的第一行加上:<%@ page contentType="text/html; charset=gb2312"%>,就可以消除乱码了。完整页面如下: <%@ page contentType="text/html; charset=gb2312"%>
<html>
<head>
<title>JSP的中文处理</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<%
out.print("JSP的中文处理");
%>
</body>
</html>
2、表单提交中文时出现乱码
下面是一个提交页面(submit.jsp),代码如下:
<html>
<head>
<title>JSP的中文处理</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<form name="form1" method="post" action="process.jsp">
<div align="center">
<input type="text" name="name">
<input type="submit" name="Submit" value="Submit">
</div>
</form>
</body>
</html>
下面是处理页面(process.jsp)代码:
<%@ page contentType="text/html; charset=gb2312"%>
<html>
<head>
<title>JSP的中文处理</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<%=request.getParameter("name")%>
</body>
</html>
如果submit.jsp提交英文字符能正确显示,如果提交中文时就会出现乱码。原因:浏览器默认使用UTF-8编码方式来发送请求,而UTF-8和GB2312编码方式表示字符时不一样,这样就出现了不能识别字符。解决办法:通过request.setCharacterEncoding("gb2312")对请求进行统一编码,就实现了中文的正常显示。修改后的process.jsp代码如下:
<%@ page contentType="text/html; charset=gb2312"%>
<%
request.seCharacterEncoding("gb2312");
%>
<html>
<head>
<title>JSP的中文处理</title>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312">
</head>
<body>
<%=request.getParameter("name")%>
</body>
</html>
3、数据库连接出现乱码 (3,4还没有实验过,不知道怎么具体操作!这是一个疑问)
只要涉及中文的地方全部是乱码,解决办法:在数据库的数据库URL中加上useUnicode=true&characterEncoding=GBK就OK了。
4、数据库的显示乱码
在mysql4.1.0中,varchar类型,text类型就会出现中文乱码,对于varchar类型把它设为binary属性就可以解决中文问题,对于text类型就要用一个编码转换类来处理,实现如下:
public class Convert {
/** 把ISO-8859-1码转换成GB312
*/
public static String ISOtoGB(String iso){
String gb;
try{
if(iso.equals("") || iso == null){
return "";
}
else{
iso = iso.trim();
gb = new String(iso.getBytes("ISO-8859-1"),"GB2312");
return gb;
}
}
catch(Exception e){
System.err.print("编码转换错误:"+e.getMessage());
return "";
}
}
}
把它编译成class,就可以调用Convert类的静态方法ISOtoGB()来转换编码。
四.自己最后写的能够处理中文的javabean:和上面一篇用的是同一例,只是在两个BEAN中有点小小的修改.
还是使用上一次说使用的javabean的例子,将其改善成完美的支持中文的输入输出的javabean.
首先要明白,在index.jsp提交表单的时候,交给了newuser.jsp调用bean的时候使用到了类UserInfo中的两个set器.(我是通过屏蔽这两个set器然后运行发现程序报错知道的这两个set器被调用,但是实际原理还是不知道,我认为调用BEAN对象的时候只是调用了一个空的构造器而已,这里还需要讨论),然后在set中将字符码转换,显示中文的一般就是那两句话:
public void setName(String value) throws IOException {
byte b[] = value.getBytes("ISO-8859-1");
this.name = new String(b);
这个是在set器里面,当调用name的set器的时候就调用这个将其转换为中文.
输出中文的修改:
在select的页面当中:
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"><meta http-equiv="Content-Type" Content="text/html; charset=ISO-8859-1">
在<head>标志符下加上这一句将编码转换成ISO-8859-1就可以了.原因:当刚才存中文字符进入数据库的时候中文字符使用的是ISO-8859-1的编码格式,所以现在要从数据库中读这些中文字符的时候也需要将取编码即charset强制设置成ISO-8859-1的编码.
代码如下:
UserInfo.java
package com.william.TestJDBC.bean;
import java.io.IOException;
public class UserInfo // 该类用来初始化所要用到的函数 包含一些set get器
{
private String userid;
private String name;
// setter property
public void setUserid(String value) {
this.userid = value;
}
//在这里做了修改,在set器中写入了一个改变编码的字节数组,然后将其附给name
public void setName(String value) throws IOException {
byte b[] = value.getBytes("ISO-8859-1");
this.name = new String(b);
}
// getter property
public String getUserid() {
return this.userid;
}
public String getName() {
return this.name;
}
}
Userselect.jsp
<%@ page language="java" contentType="text/html; charset=utf-8"
import="java.sql.*"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<jsp:useBean id="userInfo" class="com.william.TestJDBC.bean
.UserInfo"scope="page">
<jsp:setProperty name="userInfo" property="*" />
</jsp:useBean>
<jsp:useBean id="registsel" class="com.william.TestJDBC.bean
.UserRegist"scope="page" />
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
<table width="590" cellspacing="1">
<thead>
<tr>
<td>ID号</td>
<td>姓名</td>
</tr>
</thead>
<tbody>
<%registsel.setUserInfo(userInfo);
ResultSet rs = null;
rs = registsel.registSelect();
while (rs.next()) {
//在这个地方的时候不能使用刚才的方法,由于那个方法要调用构造函数又将set执行一次会出错,可以直接调用.读取的时候其实只用修改<meta>标签中的charset属性为"ISO-8859-1"即可.
%>
<tr>
<td><%=rs.getString("userID")%></td>
<td><%=rs.getString("userName")%></td>
</tr>
<%}
%>
</tbody>
</table>
</body>
</html>
五.总结
仅在编写jsp中,一般encoding编码的格式使用默认,并不涉及到.
在页面中要正确的显示中文,那么charset设置为utf-8,GB2312,GBK都能够正确无误的显示,但是ISO-8859-1不能正确显示.
在要想数据库中输入中文或者输出中文的时候,则必须将这个字符串转换成为ISO-8859-1编码格式,这样才能准确显示.