Java中的字符编码问题处理心得总结

 更新时间:2016年06月26日 15:18:02   转载 作者:阿诺  
Java中的String类默认是Unicode编码,大家平常所说的UTF-8就是使用最广的一种unicode的实现方式,以下我们还是来看一下Java中的字符编码问题处理心得总结:

当面对一串字节流的时候,如果不指定它的编码,其实际意义是无法知道的。
这句话应该也是我们面对“字符转字节,字节转字符”问题时候时刻记在脑子里的。否则乱码问题可能就接踵而至。
其实乱码问题的本质就是Encoding和Decoding用的不是一个编码,明白了这个道理就很好解决乱码问题了。
Java中常见的时候有如下:
1. String类使用byte[]的构造函数 String(byte[] bytes),String类同时提供了两个重载
(1)String(byte[] bytes, Charset charset) 
(2)String(byte[] bytes, String charsetName) 就是用来指定编码的。

2. String类的getBytes函数 byte[] getBytes() 同样有如下两个重载:
(1)byte[] getBytes(Charset charset) 
(2) byte[] getBytes(String charsetName)
所有不需指定编码的都是使用the platform's default charset, 可使用System.getProperty("file.encoding"),Charset.defaultCharset()获的。
3. PrintStream的 print(String s)同样设计到这个问题,为此PrintStream的构造函数中除了PrintStream(File file) 还有PrintStream(File file, String csn)
否则the string's characters are converted into bytes according to the platform's default character encoding,
 DataOutputStream构造时没有方法指定编码,但其提供了一个writeUTF(String str)

举开头的例子说明指定编码的必要:
如果一个网页指定编码为utf-8, <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />, 页面上有一个form,提交到一个servlet
那么用户输入的字符传过来的字节流就是按指定编码encoding的,例如你输入了"Hello你好",如果是utf-8,那么传过来的就是如下:     

[104, 101, 108, 108, 111, -28, -67, -96, -27, -91, -67] 

, 我们看到后面汉字每个用了3个字节,这个可以参考Utf-8的相关知识。
但如果你页面指定的是GBK,那传过来的就不一样了:

 [104, 101, 108, 108, 111, -60, -29, -70, -61]

所以servlet端,当使用request.getParameter的时候内部应该是调用
String s = new String(bytes, response.getEncoding())的,如果你response没有设置编码,那么就采用默认的编码null会转为java 平台的GBK,那中文就变成乱码了。
所以为了避免乱码,jsp站点一般设一个过滤器,所有的页面、servet都设置统一的编码。response.setEncoding, request.setEncoding.

Java的String内部是一个char[], char是一个用16位存储的utf-16编码的单元。为此,当要把字符、字符串转为字节输出到文件、网络,或者从文件、网络读到的字节流还原为有实际意义的字符,都要明白其编码是什么。

2016626151159929.jpg (690×492)

几点心得
1.String类始终是以Unicode编码形式存储.
2.注意String.getBytes()的使用:
   如果不带字符集参数,就会依赖于JVM的字符集编码,LINUX上一般为UNICODE,WINDOWS下一般为GBK.(要想改变JVM缺省字符集编码,启动JVM时用选项-Dfile.encodeing=UTF-8.
  为了安全起见,建议始终带参数调用,例如:String s ; s.getBytes("UTF-8")。
3.Charset类非常好用,
(1)Charset.encode 是编码,即把String按你指定的字符集编码格式进行编码后输出字节数组。
(2)Charset.decode 是解码,即把一个字节数组按你指定的字符集编码格式进行解码后输出成字符串。

举例如下:   

 String s = Charset.defaultCharset().displayName();
  String s1 = "我喜欢你,My Love";
  
  ByteBuffer bb1 = ByteBuffer.wrap(s1.getBytes("UTF-8"));

  for(byte bt:bb1.array()){
    System.out.printf("%x",bt);
  }
  //char[]用法
  char[] chArray={'I','L','o','v','e','你'};

  //CharBuffer用法
  CharBuffer cb = CharBuffer.wrap(chArray);
  //重新定位指针
  cb.flip();

  String s2= new String(chArray);

  //ByteBuffer用法
  ByteBuffer bb2 = Charset.forName("utf-8").encode(cb);

  // 利用Charset编码为指定字符集

  ByteBuffer bb3 = Charset.forName("utf-8").encode(s1);

  byte [] b  = bb3.array() ;

  // 利用Charset按指定字符集解码为字符串
  ByteBuffer bb4= ByteBuffer.wrap(b);

  String s2 = Charset.forName("utf-8").decode(bb4).toString();

相关文章

  • java中Iterator和ListIterator实例详解

    java中Iterator和ListIterator实例详解

    这篇文章主要介绍了java中Iterator和ListIterator实例详解,具有一定借鉴价值,需要的朋友可以参考下。
    2017-12-12
  • java模拟post请求发送json的例子

    java模拟post请求发送json的例子

    本篇文章主要介绍了java模拟post请求发送json的例子,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • java中利用反射调用另一类的private方法的简单实例

    java中利用反射调用另一类的private方法的简单实例

    下面小编就为大家带来一篇java中利用反射调用另一类的private方法的简单实例。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • Spring集成Struts与Hibernate入门详解

    Spring集成Struts与Hibernate入门详解

    这篇文章主要给大家介绍了关于Spring集成Struts与Hibernate的相关资料,文中介绍的非常详细,对大家具有一定的参考价值,需要的朋友们下面来一起看看吧。
    2017-03-03
  • SpringMVC Controller 返回值的可选类型详解

    SpringMVC Controller 返回值的可选类型详解

    本篇文章主要介绍了SpringMVC Controller 返回值的可选类型详解 ,spring mvc 支持如下的返回方式:ModelAndView, Model, ModelMap, Map,View, String, void,有兴趣的可以了解一下
    2017-05-05
  • Java局部内部类和匿名内部类定义与用法实例分析

    Java局部内部类和匿名内部类定义与用法实例分析

    这篇文章主要介绍了Java局部内部类和匿名内部类,结合实例形式分析了java局部内部类和匿名内部类相关定义、原理与用法,需要的朋友可以参考下
    2019-08-08
  • Java 中的伪共享详解及解决方案

    Java 中的伪共享详解及解决方案

    这篇文章主要介绍了Java 中的伪共享详解及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02
  • 全面理解Java类和对象

    全面理解Java类和对象

    下面小编就为大家带来一篇全面理解Java类和对象。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-06-06
  • java使用TimerTask定时器获取指定网络数据

    java使用TimerTask定时器获取指定网络数据

    java.util.Timer定时器,实际上是个线程,定时调度所拥有的TimerTasks。一个TimerTask实际上就是一个拥有run方法的类,需要定时执行的代码放到run方法体内,TimerTask一般是以匿名类的方式创建,下面的就用示例来学习他的使用方法
    2014-01-01
  • 通过java字节码分析学习对象初始化顺序

    通过java字节码分析学习对象初始化顺序

    今天用了jmock对进行单元测试编码,发现一个比较奇怪的语法,static使用方法,见下面例子
    2013-11-11

最新评论