经常看到有人写这样的代码:new String(“乱码”.getBytes(“GBK”),”UTF-8”),能写出这种代码其实是对编码原理一点都没有理解,这种写法根本没有任何作用,浪费资源。
Java编码涉及到的就两个对象:string和byte,编码涉及的也就两种转换:
1. String转byte,把字符串按照特定的字符集转换为字节流,通常的作法是"helloworld".getBytes("gbk")
2. byte转String,把字节流按照特定的字符集转换为字符串,通常的作法是new String("helloworld", "gbk")
Java编码的应用场景一般由以下几种:
1. 服务器与浏览器之间的通讯及展示
2. 本地文件与内存之间的交互
服务器与浏览器
对于POST请求
服务器通过响应头的编码指定返回给浏览器的字节流是什么方式编码的,浏览器通过响应头的编码来还原字符串,并展示出来。如果响应头中没有指定编码,在服务器端会用容器的默认编码,在浏览器端则用浏览器的默认编码,一般是操作系统的默认编码,中文系统通常是GB2312。
对于GET请求
由于不同的浏览器采用的编码不一样,所以经常会导致服务端读取GET请求的参数时出现乱码问题。根本的原因是,HTTP请求头的编码是给body用的,而URL的编码是无法在HTTP请求的任何参数里面指定,这就导致了对于GET请求,服务端是通过容器预设的编码来反编码URL参数的,由于预设编码是写死的,所以不管你是采用网上很多文章都推荐用UrlEncodingFilter,还是new String(“乱码”.getBytes(“GBK”),”UTF-8”),都是白费。
彻底的解决办法是,对GET请求的参数在浏览器端URL编码两次,第一次编码出来的是英文字符了,第二字编码不管采用何种字符集生成的东西都是一样的了。这样在服务端容器不管预设置的是什么编码反解出来的东西都是一样的,第二次反解则用浏览器指定的编码即可。伪代码如:浏览器端encode(encode("data"));服务器端:decode(decode("data"))
本地文件与内存
首先要明确两点:
1. 文件存储的是字节,亦即是说保存字符串为文件的时候必须指定一个字符集,如:FileUtils.writeStringToFile(new File("c:/tmp.txt"), "helloworld", "gbk"),这句代码隐含的含义是先把内存中的字符串按gbk编码为字节流,然后再写到文件中。如果你手中获取到的已经是字节流,那输出文件的时候不需要指定编码的,如FileOutputStream.write(bytes)。
2. Java内存中的字符串都是以unicode编码的,一个字符占用两个字节。当你用FileInputStream打开一个文件时,并不需要指定字符集编码的,因为这时候从文件中读入的都是字节流。但是,当你的程序后继会用的这个打开的文件处理字符时,那必须要指定编码,这也是为什么InputStreamReader这个类需要指定编码,因为它涉及到了把字节流转换为字符串的过程。
明白了上面两个流程,那你在写程序的时候只要记住:如果不涉及到string与byte之间的转换,代码里面不应该出现任何的编码操作。Java里面最常用的InpuStream和OutputStream,这两个类在操作的时候都不需要指定编码,因为文件本身是没有编码的,编码只存在于文件里面的内容(字节)。在你读入字节,并需要转换为字符时才需要编码;在你输出字节,并需要把字符转为字节是才需要编码。
哦,还有一点,char是字符,char[] chars = string.toCharArray(),所以程序中用到了char,肯定就需要byte转string,那就要记住必须在Reader中指定字符集。
最后分享一个案例:把字符串解释为DOM对象
第一种作法是:
InputStream in = new ByteArrayInputStream("<helloworld/>".getBytes("utf-8"));
DocumentBuilder.parse(in);
这种做法其实严重浪费了CPU资源,首先它把字符串转为字节流,然后DOM解释器再把字节流转为字符串。而且这种方式还带入了另外一个问题,DOM在把字节转换为字符时会读取XML第一行的字符集编码,如果XML头部声明的编码和字节流编码不一致,那就杯具了。
第二种作法是:
StringReader sr = new StringReader("<helloworld/>");
InputSource is = new InputSource(sr);
DocumentBuilder.parse(is);
这种作法避免了string>byte和byte>string两次转换,性能大大提升。由于没有涉及到字符与字节转换,不需要考虑任何编码问题,即使XML头部声明的编码与XML内容不一致,也没问题。
分享到:
相关推荐
java字符集编码乱码详解
Java关于中文乱码问题的多种解决方法,中文乱码过滤器
网上很多描述java解压中文乱码的问题,很多描述不全.由于工作需要整理出一个完整版.简单实用.下载后请从ZipUtil.java的main方法开始,一目了然. public static void main(String args[]) { new ZipUtil().unZip("E:\\...
解决JAVA读取properties中文乱码问题
JAVA常见中文乱码问题解决方法,JAVA常见中文乱码问题解决方法.
最近在做一个java生成图片的功能,由于系统字体原因,在linux上生成出来的中文是乱码,所以在网上找了N多的资料,最终才把问题解决。很多人说把字体放到jdk安装目录下的Jre的fonts目录下,根本是无效的。且Centos6和...
java编码格式问题,对常见的java中文乱码作出分析及提出解决方案
java解决中文乱码问题
java+mysql 乱码 SSH hibernate设置+mysql设置
主要为大家分享了介绍了java中文乱码之解决URL中文乱码问题的方法,感兴趣的小伙伴们可以参考一下
解决乱码的各种方法总结,包括数据库的解决方案,个人觉得比较详细有使用价值
java编程中乱码问题解决方案,解决一些常见的java开发环境中的乱码问题
java中文乱码解决之道(4)java编码转换过程Java开发Java经验技巧共5页.pdf.zip
JAVA 乱码问题,JAVA 乱码问题,JAVA 乱码问题JAVA 乱码问题JAVA 乱码问题JAVA 乱码问题
java中文乱码处理,本文中几个方法解决了中文乱码的问题 希望对你有帮助
freemarker入门实例,直接运行(junit)测试类
java插入mysql中文乱码解决
java编码中的中文问题是一个老生常谈的问题了,每次遇到中文乱码LZ要么是按照以前的经验修改,要么则是baidu.com来解决问题。阅读许多关于中文乱码的解决办法的博文后,发现对于该问题我们都(更加包括我自己)没有...
解决java压缩中文乱码,java.util.zip中不支持中文,通过该代码进行修改即可支持中文,不用第三方插件