网络编程 | 站长之家 | 网页制作 | 图形图象 | 操作系统 | 冲浪宝典 | 软件教学 | 网络办公 | 邮件系统 | 网络安全 | 认证考试 | 系统进程
Firefox | IE | Maxthon | 迅雷 | 电驴 | BitComet | FlashGet | QQ | QQ空间 | Vista | 输入法 | Ghost | Word | Excel | wps | Powerpoint
asp | .net | php | jsp | Sql | c# | Ajax | xml | Dreamweaver | FrontPages | Javascript | css | photoshop | fireworks | Flash | Cad | Discuz!
当前位置 > 网站建设学院 > 网络编程 > Java
Tag:注入,存储过程,分页,安全,优化,xmlhttp,fso,jmail,application,session,防盗链,stream,无组件,组件,md5,乱码,缓存,加密,验证码,算法,cookies,ubb,正则表达式,水印,索引,日志,压缩,base64,url重写,上传,控件,Web.config,JDBC,函数,内存,PDF,迁移,结构,破解,编译,配置,进程,分词,IIS,Apache,Tomcat,phpmyadmin,Gzip,触发器,socket
网络编程:ASP教程,ASP.NET教程,PHP教程,JSP教程,C#教程,数据库,XML教程,Ajax,Java,Perl,Shell,VB教程,Delphi,C/C++教程,软件工程,J2EE/J2ME,移动开发
本月文章推荐
.动态Proxy与Java ACL用户访问控制.
.能够在非中文平台上显示汉字吗.
.KickJava.com 推出Java原代.
.Skip 方法.
.Jboss下MSSQLServer配置指导.
.Tomcat5.5数据库连接池配置.
.最简单的Hibernate入门简介.
.EJB中数据验证出现在什么地方最合.
.String 对象.
.JXTA Java标准版本 2..
.利用Servlet开发企业级三层Web应.
.JGraph经典常见问题解答(FAQ).
.JAVA下的GZIP应用.
.EJB介绍.
.对象引用是怎样严重影响垃圾收集.
.使用Java语言编写程序最容易犯的.
.JavaClassLoader与Package机制.
.Eclipse快速上手指南 (1).
.在java中利用动态编译实现eval.
.建模的误区.

分析Java中乱码问题产生的根源

发表日期:2008-1-5



  最近用到了字符串的压缩,用到了GZipInputStream和GZipOutputStream,再次碰到了阔别已久的中文乱码问题。
  
  看了一些相关的文章,觉得我们之所以会碰到这样那样的乱码问题,基本上都是由于我们在某些地方隐含了byte到char的转换,而这种隐含的转换采用的是iso-8859-1的编码进行的。
  
  以jsp页面中文传递为例子,假设客户端的编码是GB2312,表单中的中文提交后,首先根据GB2312编码转换为字节流,到达服务器端后,假如我们直接在servlet中调用request.getParameter(String name)等方法,由于方法返回的是String 对象,所以其中必然隐含了一次从byte到char的转换,错误也就是在这里产生的,假如这次转换采用的编码是iso-8859-1,得到的当然是乱码。
  
  public class Login
  extends HttpServlet {
  private static final String CONTENT_TYPE = "text/Html; charset=UTF-8";
  .....
  //Initialize global variables
  public void init() throws ServletException {
  }
  
  //Process the HTTP Get request
  public void doGet(HttpServletRequest request, HttpServletResponse response) throws
  ServletException, IOException {
  String name = request.getParameter("userid");//隐含的转换
  
  name = new String(name.getBytes("iso-8859-1"), "GB2312");//还原字节,重新构造
  
  response.setContentType(CONTENT_TYPE);
  PrintWriter out = response.getWriter();
  out.println("<html>");
  out.println("<head><title>Login</title></head>");
  out.println("<body bgcolor=\"#ffffff\">");
  out.println("<p>The servlet has received a GET. This is the reply.</p>");
  out.println("</body>");
  out.println("</html>");
  out.close();
  }
  }
  
  幸好,以iso-8859-1进行的默认转换不会损失字节,也不会增加字节,我们只要按照iso-8859-1的方式返回原来的字节数组,重新按照GB2312的方式进行byte 到char的转换就可以了。
  
  再以压缩流为例(文件流实际上也是一样的)
  
  public String uncompress(byte[] cmp) {
  String ret = "";
  int i;
  byte[] buf = new byte[512];
  try {
  /**
  *新的方式,始终保持以字节为核心,最后再按照合适的编码进行组装
  */
  BufferedInputStream bis = new BufferedInputStream(new GZIPInputStream(new
  ByteArrayInputStream(cmp)));
  
  /**
  * 以前的方式
  * 在 new InputStreamReader()的时候发生了隐含的byte到char的转换,导致之后出来的都是乱码
  */
  //   BufferedReader bis = new BufferedReader(new InputStreamReader(new
  //     GZIPInputStream(new
  //             ByteArrayInputStream(cmp))));
  
  ByteArrayOutputStream baos = new ByteArrayOutputStream();
  BufferedOutputStream bos = new BufferedOutputStream(baos);
  
  while ( (i = bis.read(buf)) > 0) {
  bos.write(buf, 0, i);
  }
  bos.close();
  baos.close();
  bis.close();
  ret = new String(baos.toByteArray());//用平台默认的编码进行组装,我是GB2312
  }
  catch (IOException ex) {
  ex.printStackTrace();
  }
  
  return ret;
  }
  
  reader是以字符为核心,inputStream是以byte为核心的,当他们转换的时候就会进行byte到char的转换,所以我们要注重自己的调用的顺序。
  
  我们假如今后再碰到乱码的问题,就去找找自己是不是什么地方进行了隐含的byte到char的转换。
上一篇:在.NET上安装XBike以及操作方法 人气:593
下一篇:国际化:理解Java平台上的Locale 人气:797
浏览全部Java的内容 Dreamweaver插件下载 网页广告代码 祝你圣诞节快乐 2009年新年快乐