zoukankan      html  css  js  c++  java
  • 关于Java乱码

    乱码本质:读取二进制时采用的编码与最初将字符转成二进制时的编码不一致。

    编码(获得二进制数组的过程)时不抛出异常,数据就不会被破坏。

    Java关于乱码(MessyCode)问题

    Java使用的是Unicode编码;

    String str = "双引号里是字符串字面量";str在JVM中的编码是Unicode编码表示的;

    除了这种程序内部的数据之外,还常常从外部获取各种各样的数据让程序处理,比如文件、数据库,而这些数据的编码格式是多种多样的,可能是UTF-8、GBK,这样的一些数据在JVM中是以什么编码表示的?

    字符集编码编码格式是两个概念

    字符集编码:由某个组织制定的一张字符与编号的映射关系表,如:10001=="我",10002=="们",Unicode字符集就是这样的一张关系表。

    UTF-8是一种实现了Unicode字符集中部分字符编码的编码格式,它存在的目的:为了保存或传输数据。那既然在字符集中已经有了映射关系了,为何还要再来编码?

    因为:考虑到文件大小的问题、使用效率的问题、和其它字符集区分的问题。

    UTF-8编码是对Unicode字符集中哪部分编码?就是"字符编号",例如上面的10001、10002

    对于UTF-8编码规则可网上查阅。

    JVM中表示字符串"我们"使用的编码为"1000110002"这样的格式,即使用的是Unicode的编号,

    当通过IO将一个以UTF-8编码的文本文件读入内存时:

    new InputStreamReader(new FileInputStream(new File("文本文件路径")),"UTF-8");

    这里指定的"UTF-8"即文件的编码格式,它的目的是告诉负责解码的对象要按"UTF-8"的编码格式来解码成JVM使用的Unicode编码,若这里指定为"gbk"则得到乱码。

    String str="文件内容",str此时已是Unicode编码。

    例:

    String yuanlai="我是一个字符串";

    String result=new String(yuanlai.getBytes("utf-8"),"gbk");->输出result乱码,

    将Unicode编码的yuanlai按utf-8的编码格式进行编码,得到utf-8编码的字节数组;将字节数组按GBK的编码格式来解码成Unicode编码的字符。UTF-8和gbk不兼容,二者使用了不同的编码集,故乱码。

    进行http请求时,我们需告诉对方我们发送的数据的编码格式是什么,若对方按照我们告知的编码格式来解码,而我们却把错误的编码格式告诉了对方,则对方收到乱码。

    "这是一个字符串".getBytes(),这样编码得到的字节数组是操作系统默认的编码格式。

    import java.io.UnsupportedEncodingException;
    
    public class MessyCode {
        public static void main(String[] args) throws UnsupportedEncodingException {
            String original="这是一个字符串,是Unicode编码的。恭喜發財";
            System.out.println("原有字符串:"+original);
            //将Unicode编码按照gbk编码格式进行编码
            byte[] GBK_bytes = original.getBytes("gbk");
            /*
            本来是gbk编码的字节数组,我们使用utf-8来解码,当然此时必然会是乱码
            注:若第一次解码时使用这种错误的解码方式,则后面将无法再恢复,
            下面的例子可以看到
             */
            String UTF8_str=new String(GBK_bytes,"utf-8");
            System.out.println("UTF-8解码后的字符串:"+UTF8_str);
            /*
            接下来我们把该字符串按照UTF-8的编码格式再编码回去,
            但这时GBK_bytes和UTF8_bytes已经完全不同了,
             */
            byte[] UTF8_bytes=UTF8_str.getBytes("utf-8");
            /*
            接着我们再来按照GBK的编码格式来解码
            得到的自然是乱码
             */
            String UTF2GBKstr=new String(UTF8_bytes,"gbk");
            System.out.println("GBK解码UTF-8编码后的字符串:"+UTF2GBKstr);
            /*
            但是,若第一次解码时使用单字节的编码格式来解码,则后面是可以再恢复的
            但前提要保证该单字节的编码会利用上所有的8位
            也就是说可以表示256个字符的才行
    
    
            单字节的编码格式有两种,ASCII和ISO-8859-?
            ASCII使用了7位来表示字符,最高位永远为0,其可以表示的范围只有128个字符
            ISO-8859-?(问号表示1,2,...,15,16(没有12),表示15个字符集)
            使用8位来表示字符,总共可以表示256个字符
    
            这两种单字节编码,ISO-8859-1最常用
             */
            //转换为ASCII码的字符串
            String ASCII_str=new String(GBK_bytes,"ASCII");
            System.out.println("ASCII解码后的字符串:"+ASCII_str);
            //再将ASCII转换为GBK
            String GBK_str=new String(ASCII_str.getBytes("ASCII"),"gbk");
            System.out.println("将ASCII编码按照gbk编码格式解码:"+GBK_str);
    
    
            String ISO_str=new String(GBK_bytes,"ISO-8859-1");
            System.out.println("ISO-8859-1解码后的字符串:"+ASCII_str);
            //再将ASCII转换为gbk
            String GBK_str1=new String(ISO_str.getBytes("ISO-8859-1"),"gbk");
            System.out.println("将ISO-8859-1编码按照GBK编码格式解码:"+GBK_str1);
        }
    }
    

    更优地克服困难。

    Java GUI组件上汉字乱码问题

    按钮上文字乱码;解决:Button改成JButton,即awt换成swing

    jsp中超链接传参乱码

    jsp页面中,超链接传参乱码,?后面的键值对的值为中文会出现这种问题

    解决:JSP在tomcat中,D:apache-tomcat-9.0.13confserver.xml中Connector节点(只有一个未注释的Connector节点)内加:

    URIEncoding="GBK"(原来文件没有);然而加这句话后会出现一个新问题:

    当jsp A跳转到jsp B时,?传参有中文,jsp B在加载时使用js获取?后参数,参数会被转码,

    解决:jsp A中:encodeURI(....jsp?键=中文值),encodeURI函数的返回值仍为一个URL,

    jsp B中js函数(页面加载时做什么)里写:decodeURI(转了码的参数值),decodeURI函数返回中文参数值。

    总结:虽然?传参中文乱码可以解决,但尽量别传中文;可以传英文,目标页面接收到再识别判断,这也是可以的。

  • 相关阅读:
    【Anagrams】 cpp
    【Count and Say】cpp
    【Roman To Integer】cpp
    【Integer To Roman】cpp
    【Valid Number】cpp
    重构之 实体与引用 逻辑实体 逻辑存在的形式 可引用逻辑实体 不可引用逻辑实体 散弹式修改
    Maven项目聚合 jar包锁定 依赖传递 私服
    Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
    mysql案例~tcpdump的使用
    tidb架构~本地化安装
  • 原文地址:https://www.cnblogs.com/yyjh/p/10618148.html
Copyright © 2011-2022 走看看