在JAVA开发中解决了中文问题和解决方案
在应用开发过程中,总会出现一些“难以理解”的系统缺陷和“难以解决”的问题。事实上,通过仔细分析,大多数问题仍然可以解决,而无需购买昂贵的产品。
■JDBC ODBC Bridge的bug及其解决方案 在编写数据库管理程序时,发现JDBC-ODBC Bridge存在不易发现的bug。将数据插入数据表时,如果是英文字符,则存储内容完全正确。如果存储中文字符,一些数据库只能存储前七八个中文字符,其他内容被切断,导致存储内容不完整(一些数据库不存在此问题,如sybase SQL Anywhere 5.0。JDBC-ODBC Bridge仍然有无法建表的bug)。
对于大多数需要存储中文信息的Java程序员来说,这是个坏消息。要么用其他语言编程,要么选择其他昂贵的数据库产品。“一次写作,到处运行”的目标也大大降低。中文信息可以在存储之前通过灵活处理来解决这个问题吗?答案是肯定的。
解决问题的具体思路和方法 Java采用Unicode编码,中英文字符采用16bit存储。由于英文信息的存储是正确的,所以按照一定的规则,将中文信息转换成英文信息后,自然不会出现截尾现象。然后在阅读信息时进行逆向操作,将英文信息还原为中文信息。根据GB2312的编码规则,汉字一般是ASCII码,两个高位为1。在转换过程中,删除一个汉字的两个高位1,然后在恢复过程中添加两个高位1。为了处理含有英文字符的中文字符串,英文字符需要添加一个Byte 0标记。在任何类别中都可以使用以下两种公共静态方法。
将中英文字串转换为纯英文字串 public static String toTureAsciiStr(String str){
StringBuffer sb = new StringBuffer();
byte[] bt = str.getBytes();
for(int i =0 ;i〈bt.length;i++){
if(bt[i]〈0){
file://是汉字去高位1
sb.append((char)(bt[i]&&0x7f));
}else{//是英文字符 补0作记录
sb.append((char)0);
sb.append((char)bt[i]);
}
}
return sb.toString();
}
还原转换后的字串 public static String unToTrueAsciiStr(String str){
byte[] bt = str.getBytes();
int i,l=0,length = bt.length,j=0;
for(i = 0;i〈length;i++){
if(bt[i] == 0){
l++;
}
}
byte []bt2 = new byte[length-l];
for(i =0 ;i〈length;i++){
if(bt[i] == 0){
i++;
bt2[j] = bt[i];
}else{
bt2[j] = (byte)(bt[i]|0x80);
}
j++;
}
String tt = new String(bt2);
return tt;
}
例子在实际编程中非常有效,但存储的中文信息需要同样的处理才能被其他系统使用。如果英文字符出现在中文字符串中,实际上会增加额外的存储空间。
■Servlet在Solaris下编程的中文问题及解决方案 在使用Java开发Internet上的应用系统时,发现在Windows下调试完全正常的Servlet并上传到Solaris 在服务器上,运行失败——返回的网页不能显示中文,所有中文信息都应该是乱码;用中文信息作为关键词,无法正确检索数据库。后来,通过添加检查代码等方法,对故障原因进行了探测:
显示乱码的主要原因是通过类别 setcontentententypense提供Httpservletresponse的方法 不能改变返回给客户的数据的编码方式,正确的编码方式应该是GB2312或GBK,但实际上是缺失的ISO859-1。由于客户提交的中文信息通过浏览器编码到达服务器后,Servlet无法正确解码,因此无法检索中文信息。
例子说明了显示乱码的解决方案 Servlet 一般做法如下:
public class ZldTestServlet extends HttpServlet {
public void doGet (HttpServletRequest request,HttpServletResponse response)throws ServletException, IOException{
file://在使用 在Writer将数据返回到浏览器之前,设置 content-type header ,在这里设置相应的字符集gb2312
response.setContentType("text/html;charset=gb2312");
PrintWriter out = response.getWriter(); file://*
// 正式返回数据
out.println("〈html〉〈head〉〈title〉Servlet test〈/title〉〈/head〉" );
out.println("这是一个测试页!";
out.println("〈/body〉〈/html〉");
out.close();
}
...
}
要解决页面显示乱码的问题,需要用以下内容替换*代码:
PrintWriter out = new PrintWriter(new OutputStreamWriter(response.getOutputStream(),“gb2312”;
解决Solaris中文信息检索问题 当浏览器使用表单向服务器提交信息时,通常使用x-www-form-urlencoded MIME格式编码数据。如果采用get方法,编码后将参数名称和参数值附加到URL中,则称为Java中的查询串(query string)。
在Servlet程序中,如果采用Servletrequest的方法获取参数值,则在Solaris环境中无法正确解码汉字。因此,无法正确检索数据库。
在Java 1.2的包——java.在net中提供URLEncode和URLDecode类别。类URLEncode提供XRLEncode-www-form-urlencoded格式转换给定串的方法。类urlencode提供了一种逆向方法。
在编写在线114查询Servlet时,首先获取查询串,然后使用URLDecode解码,然后从解码串中获取参数,很好地解决了Solrais环境中的中文信息检索问题。这里不提供源代码。如有必要,请与作者联系。
