zoukankan      html  css  js  c++  java
  • Java编码问题原因以及解决


    一、文件编码

      Unicode 是首选编码。Unicode 是全球范围的字符编码标准。

               小结: GBK 与unicode之间的转换是通过gbk unicode映射表。

      UTF-8 与unicode之间的转换是通过转换规则公式

                 所以说,unicode是核心中介。Gbk要转换成utf-8的话,先转成unicode。然后unicode再转换成utf-8;反之亦然。


    二、XML编码问题


      ★ 编码属性应当被指定为文档被保存时所使用的编码


      ★ encoding声明的编码属性


      ★ W3C定义了三条XML解析器如何正确读取XML文件的编码的规则:


        1.如果文挡有BOM(字节顺序标记,一般来说,如果保存为unicode格式,则包含BOM,ANSI则无),
        就定义了文件编码(另存为文件时,选择的编码格式)。


        2.如果没有BOM,就查看XML encoding声明的编码属性。


        3.如果上述两个都没有,就假定XML文挡采用UTF-8编码


      ★ Eclipse等编辑器会根据XML encoding声明的编码属性来保存文件。

            ★移除无效的XML字符

        /**   * 移除无效的XML字符  

          * 官方定义了XML的无效字符分为三段:      0x00 - 0x08      0x0b - 0x0c      0x0e - 0x1f  

           * @param value  

          * @return   */  

        public static String removeInvalidXMLCharacter(String value)     {

            return value.replaceAll("[\x00-\x08\x0b-\x0c\x0e-\x1f]", "");    

        }

    三、String编码问题


      ★ 对于 String s = "你好哦!";的理解。


        1、如果源码文件是GBK编码, 操作系统(windows)默认的环境编码为GBK,那么编译时, JVM将 按照GBK编码将字节数组解析成字符,然后将字符转换为unicode格式的字节数组,作为内部存储。
                 如果源码文件是UTF-8编码, 我们需要通知编译器源码的格式,javac -encoding utf-8 ... , 编译时,JVM按照utf-8 解析成字符,然后转换为unicode格式的字节数组,
                 那么不论源码文件是什么格式,同样的字符串,最后得到的unicode字节数组是完全一致的,显示的时候,也是转成GBK来显示(跟OS环境有关)


        2、System.out.println( new String(s.getBytes(),"UTF-8"));     // 错误,因为getBytes()默认使用GBK编码, 而解析时使用UTF-8编码,肯定出错。

      ★如何正确的将GBK转UTF-8 ? (实际上是unicode转UTF-8) 

                 注意:并不算new String( s.getBytes("GBK") , "UTF-8); //源码文件是GBK格式,或者这个字符串是从GBK文件中读取出来的, 转换为string 变成unicode格式

        //字符串在内存中是unicode格式
           String gbkStr = "你好哦!";

                  //利用getBytes将unicode字符串转成UTF-8格式的字节数组
             byte[] utf8Bytes = gbkStr.getBytes("UTF-8");

                  //然后用utf-8 对这个字节数组解码成新的字符串

        String utf8Str = new String(utf8Bytes, "UTF-8");


        即:new String( s.getBytes("utf-8") , "utf-8");  

      ★new String(s.getBytes("iso-8859-1") ,"GBK")


        一般用来转换原来是GBK编码的,被转换成了iso-8859-1,现在恢复回GBK。
        注意:并不是所有转换都是可逆的,iso-8859-1的字节数组是单字节的,所以能转换。

        ★读写时,可以指定编码

    四、JAVA编码问题


      ★文件加载
        java文件编码格式:默认与操作系统一致,但可修改。
        编译成Class文件:class文件的编码固定为UTF-8
        load class文件到JVM :Unicode
        内存:Unicode
        理解:不管文件的编码格式是什么,加载到JVM都是一样的。

      ★网络传输都是以字节为单位,所以所有的数据都必须能够被序列化为字节。在 Java 中数据被序列化必须继承 Serializable 接口。


      ★从网络中读取资源文件的时候,无论当前java文件编码为何值,得到的一个个字节只与读取的资源文件保存的编码有关。


      ★对于读取网络资源乱码问题,如果能够知道资源的编码格式,只需要在转成字符串的过程中使用这种编码就


      所以,关键问题落在了判断资源文件编码方式是那种。

    五、encodeURI与encodeURIComponent 与 escape

      ★对于不同浏览器编码有些不同,所以需要编码。两者都是使用UTF-8编码规则来编的

      ★区别 :

                      encodeURI用于整个URL ,对于url里面的预留符号等不进行编码;

                      encodeURIComponent用于参数段,编码更彻底:url里面的预留符号等会编码;

                      escape用于对字符串进行编码,不适用于URL。escape的0-255以外的unicode值进行编码时输出%u****格式,其它情况下escape,encodeURI,encodeURIComponent编码结果相同

      ★ escape/unescape、encodeURI/decodeURI、encodeURIComponent/decodeURIComponent 主要的区别还有不编码的字符个数。

        1)escape不编码的字符有69个

          *、+、-、.、/、@、_、0~9、a~z、A~Z而且escape对0~255以外的unicode值进行编码时输出%u****格式。

        2)encodeURI不编码的字符有82个

          !、#、$、&、'、(、)、*、+、,、-、.、/、:、;、=、?、@、_、~、0~9、a~z、A~Z

        3)encodeURIComponent不编码的字符有71个

          !、'、(、)、*、-、.、_、~、0~9、a~z、A~Z

      ★对URL中的中文参数需要两次编码的问题。


        (1)如果服务器的编码是UTF-8,那么下面是不会出现乱码的。否则,出现乱码。
          前端:var url1=encodeURI(url);
          后台:String name=request.getParameter("name");

        (2)不管服务器编码,都不会出现乱码


          前端:url1=encodeURI(url);把url中的中文编为ASCII码。
             url2=encodeURI(url1);对ASCII码进行编码


          后台://这里tomcat自动解码。tomcat的配置文件没设置,那么默认是ISO-8859-1
            String name1=request.getParameter("name");
            String name2 = java.net.URLDecoder.decode(name1,"UTF-8");


           不管是按 GBK 还是 UTF-8 还是 ISO-8859-1 都好,都能够正确的得到url1。因为ASCII码的编码用GBK、UTF-8、ISO-8859-1编码的结果是相同的。


      ★对于POST提交数据,浏览器会根据网页的ContentType("text/html; charset=GBK") 中指定的编码进行对表单中的数据进行编码。

        服务端:request.setCharacterEncoding()设置编码,然后通过request.getParameter获得正确的数

    六、JAVA中的乱码


    ★浏览器用utf-8解析:

        (手动)==> 在浏览器中右键选择编码格式为utf-8
        (智能)==> 在文件中写入如: <meta name="content-type" content="text/html; charset=UTF-8">
        通过<meta>标签模拟response头,起到告诉浏览器用utf-8的编码解析
        (智能)==> response.setContentType("text/html;charset=utf-8");
        或 response.setHeader("content-type","text/html;charset=UTF-8");
        或 response.getOutputStream().write("<meta http-equiv='content-type' content='text/html;charset=utf-8'>".getBytes());


        目的是为了控制浏览器的行为,即控制浏览器用UTF-8进行解码

        常用:
          <meta name="content-type" content="text/html; charset=UTF-8">或<meta charset="utf-8">
          <%@ pageEncoding="utf-8"%>
          <?xml encoding="UTF-8"?>
    ★response.setCharacterEncoding("UTF-8"); 设置的是response存储数据的码表。 目的是用于response.getWriter()输出的字符流的编码。


        如果是response.getOutputStream()是不需要此种解决方案的,因为这句话的意思是为了将response对象中的数据以UTF-8解码后的字节流发向浏览器

    ★response.setContentType("text/html;charset=utf-8");内部也调用了setCharacterEncoding方法,相当于setCharacterEncoding("UTF-8");和setHeader("content-type","text/html;charset=UTF-8");
    ★response.setCharacterEncoding可以覆盖之前的response.setContentType


    ★ 1.IE和WEB服务器默认通过ISO-8859-1进行编码,可以使用setCharacterEncoding是设置字符的编码
      2.URL默认只支持ISO-8859-1


    ★ Get请求:参数QueryString内容默认解码方式问ISO8859-1,而且使用request.setCharacterEncoding("utf-8")也无法解决问题。


        1.修改tomcat服务器的配置文件<Connector>节点 URIEncoding="utf-8"
        2.如果没有设置URIEncoding,那么使用new String(username.getBytes("ISO-8859-1"),"UTF-8");

        3. useBodyEncodingForURI=”true”:使用Header中ContentType中定义的Charset

    ★ url、cookie、ajax get请求,一般用URLEncoder,对于url参数需要两次编码

    ★ Post请求 request.setCharacterEncoding("UTF-8"); 只对Post请求有效

    七、JAVA在Linux中生成的文件出现文件名乱码的问题

         原因:sun.jnu.encoding和liunx系统编码不一致。

         1. java启动的所有环境变量:

            ps -ef|grep xxxx 获取pid

            jinfo pid 查看所有环境变量,其中就有:

        file.encoding = GBK

        user.country = CN

        sun.jnu.encoding = GB2312

        user.timezone = Asia/Shanghai

         2. 如果启动命令没有指定这些参数,那会受到

             cd ~用户目录下的.bash_profile文件中配置的字符集编码等影响。

         3. 查看系统的语言和字符命令:echo $LANG  或 locale

        System.out.println("user.language = "+System.getProperty("user.language"));
        System.out.println("user.country = "+System.getProperty("user.country"));
        System.out.println("user.region = "+System.getProperty("user.region"));
        //查看当前系统的字符编码方式
        System.out.println("Charset.defaultCharset().name() = "+Charset.defaultCharset().name());
        //查看当前系统的编码方式
        System.out.println("file.encoding = "+System.getProperty("file.encoding"));
        System.out.println("sun.jnu.encoding = "+System.getProperty("sun.jnu.encoding"));
  • 相关阅读:
    selenium3 + python
    selenium3 + python
    Linux 文件查找
    Linux 重定向与管道
    MySQL —— 基本查询方法
    Linux 用户和文件权限管理
    Linux bash介绍与使用
    Linux 文件操作
    Linux 文件系统简介
    Linux 帮助命令
  • 原文地址:https://www.cnblogs.com/caoshouling/p/8644596.html
Copyright © 2011-2022 走看看