zoukankan      html  css  js  c++  java
  • Java中文字符处理的四大迷题

        虽然计算机对英文字符的支持非常不错,我们也恨不得写的程序只会处理英文的数据,但是昨为中国人,无可避免地要处理一些中文字符。当很简单的一件事情,遇到了中文,一切就不同了!本文就会讲述实际生产环境中遇到的四个中文迷题,欢迎大家参与补充!

    1、“我”讲的其它机器听不懂?

        当把一串中文字符,通过HTTP、TCP方式传递到另外一个系统时,会经常惊奇地发现,在发送前还是好好的,但是收到后却全坏了!怎么办?下面提供几种情况,对症下药:

        (1)发送时使用的GET请求

         要特别注意传递参数时,不要直接使用中文(如?key=热情),这基本就宣告了这个代码在某个浏览器、某个机器上,对方收到的东西就是乱码了。必须要对传递的参数进行Url Encode,接受方再进行Url Decode,取出来的数据基本就是OK的了。注:某些Java框架(如Spring)的RestTemplate会自动对GET方式的调用参与进行Encode、Decode,你就可以不用再人工去做了。

        (2)使用了byte传递数据

         在使用MQ、原生Socket等场景下,有时要用byte传递数据。这时一定要对String的getBytes方法传递编码参数,一般用"UTF-8",且接收方则用new String(bytes, "UTF-8")来构造字符串,不然也有乱码风险!建议对需要用byte传递数据的场景,尽量转为Base64编码的方式进行传递,更方便去调试程序。

        (3)设置运行环境编码

         如果你的系统默认编码未设置对,那么默认的Java代码运行环境也不对,所以一要在程序运行时对Java代码运行环境进行设置。以Linux Shell为例,在启动应用的shell里,增加

    export LANG=en_US.UTF-8

         这可以保证应用在调用系统命令行时,运行环境是以UTF-8编码的。另外如果是Tomcat,那么的脚本处也加上参数项:

    -Dsun.jnu.encoding=UTF-8 -Dfile.encoding=UTF-8 -Duser.language=en -Duser.country=US

        再修改tomcat默认编码(ISO-8859-1)方法,修改tomcat根目录的conf下的server.xml,Connector元素添加URIEncoding="UTF-8"属性:

    <Connector port="8080" protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443" URIEncoding="UTF-8" />

        这可以保证应用的Java代码的默认运行是在UTF-8编码基础上的,如果需要通信的系统全设置为UTF-8,可以避免诸多编码转换!

    2、浏览器不认识“我”?

         一般来说,浏览与应用的交互就是GET、POST请求了,当然还有PUT、DELETE请求,不过触类旁通,不需要讲太多。

         POST请求的中文数据,经常是可以正常在前后台传递的,但是GET请求就没那么幸运了,一定要记得进行URL Encode与Decode,养成好的编码习惯,减少后续调试代码的难度与时间。

    3、猜一猜“我”说的是什么?

         在读写含中文文本的文件时,有时候也会读出乱码来,原因是因为程序的运行编码永远只有默认的一种的,那么如果不带编码参数地去读取文件,由于文件编码可能与程序编码不同,最后读出来的就是乱码了。这个时候,就需要写程序去“猜”文件的编码了。

         现在有许多开源的识别编码的类库可以直接使用,但是也并不全是ok的,常见的编码能识别就好,像这些:UTF-8、GB2312、GBK、GB18030、UTF-16、US-ASCII、Big5、ISO-8859-1,遇到的概率非常大。我这里推荐几个:EncodingDetecotrjChardet

         在读取到byte后,通过编码识别再存为相应的String,就可以得到正常的中文了。

    4、听说UTF-8还有BOM?

         BOM,在UCS编码中有一个叫做"ZERO WIDTH NO-BREAK SPACE"的字符,它的编码是FEFF,这就是所谓的BOM头了,它的UTF-8编码是EF BB BF。在Windows系统上,默认用记事本存储为UTF-8格式,是有BOM的,但是Linux下却是默认无BOM的。缺了BOM的文件,经常在Windows下就识别出现错位、乱码等问题。解决之道就是在读取文件、byte的前几个字节,如果无BOM就给它加上BOM。

     1     /**
     2      * 判断文件是否有BOM
     3      * 
     4      * @return
     5      */
     6     public static boolean hasBom(File file) {
     7         FileInputStream input = null;
     8         try {
     9             input = new FileInputStream(file);
    10             byte[] buf = new byte[1024];
    11             if ((input.read(buf, 0, 1024)) != -1) {
    12                 if (buf[0] == (byte) 0xEF && buf[1] == (byte) 0xBB && buf[2] == (byte) 0xBF) {
    13                     return true;
    14                 }
    15             }
    16             return false;
    17         } catch (IOException e) {
    18             _logger.error(e);
    19             return true;
    20         } finally {
    21             if (input != null) {
    22                 try {
    23                     input.close();
    24                 } catch (IOException e) {
    25                     _logger.error("资源释放失败!", e);
    26                 }
    27             }
    28         }
    29     }

          如果无BOM,则在传给Windows的地方或需要导出的地方这前先加上:new byte[] {(byte) 0xEF, (byte) 0xBB, (byte) 0xBF} 这些字节。

         以上这些点如果注意了,常见的中文编码问题就解决了,如果还有新的坑,博主会在此更新哈。

         转载请注明原址:http://www.cnblogs.com/lekko/p/4943581.html 

  • 相关阅读:
    Unity3d vector3.forward和transform.forward的区别!
    UGUI实现摇杆
    UGUI实现拼图游戏
    Unity3d打包发布Android程序
    兼容PC和手机触摸代码
    unity3d中Transform组件变量详解
    运算符重载
    扩展方法
    string.Format格式化输出
    网络编程之Socket的TCP协议实现客户端与客户端之间的通信
  • 原文地址:https://www.cnblogs.com/lekko/p/4943581.html
Copyright © 2011-2022 走看看