字符集介绍和DM插入时出现乱码

  1. 编码的历史和常⽤字符集
    ① 字符集:
    顾名思义是“许多字符的集合”,这些字符组成⼀套符号系统,可以组合起来形象 的表达各种含义。⽐如26个英⽂字⺟加上标点符号可以组成“英⽂字符集”,这个字 符集的组合可以形成英美⼈可以理解的⼀套⽂字系统。再⽐如新华字典中的所有汉 字加上标点符号可以组成“中⽂字符集”,这个字符集的组合可以形成中⽂⽂字系统。
    ② 字符编码:
    “字符编码”字⾯意思就是“对字符进⾏编码”。对字符编码的最⼤⽬的是为了传输、 储存信息。⼈和⼈之间交流,⽆⾮两种⽅式:⼝头交流,书⾯交流。书⾯交流就是 把“字符”“画”到纸上或者其他介质上,然后传输给别⼈看。但是当传输过程遇到了特 殊情况,就出现问题了,⽐如和盲⼈书⾯交流;信息加密;使⽤计算机交流。这就 产⽣了编码的必要性。
    ③ 编码模型的建⽴⽅法:
    在计算机中,要建⽴⼀种“字符编码模型”,需要四步: 1、要有⼀个字符库,确定这些字符⾜够表意。 ⽐如ASCII字符集,已经⾜够表⽰ 英语,但不能表⽰中⽂,于是产⽣GB2312字符集。 2、第⼀层编码,给每个字符编个数字,英⽂叫Code Point 或 Code Position。⽐如 ASCII字符集中,65表⽰“A”,97表⽰“a”。 3、第⼆层编码,确定表⽰字符的⼆进制位数(8位,16位,32位)。ASCII使⽤7 位,DBCS(双字节字符集)使⽤16位。 4、第三层编码,确定字符⼆进制值的存储格式(⼤端法,⼩端法)。⽐如X86机 器使⽤⼩端法。
    ④ ISO-8859:
    为了表⽰更多的欧洲等国家使⽤的字符,ISO组织对原始的 ASCII 编码范围进⾏ 了扩充,统⼀了⼀套标准字符集,就是ISO-8859 ,向下兼容ASCII ,采⽤⼀个字节 256 种不同状态来表⽰ 256 种不同的字符。包括ISO-8859-1、-2等17种适⽤于欧洲 不同地区的字符集。例如:ISO-8859-1 的较低部分(从 1 到 127 之间的代码)是最 初的7位 ASCII。ISO-8859-1 的较⾼部分(从 160 到 255 之间的代码)全都有实体 符号对应。ISO-8859-1编码是⼀个8位的容器,Latin1是ISO-8859-1的别名,有些环 境下写作Latin-1。
    ⑤ GB2312:
    1)把ASCII码中127号之后的奇异符号直接取消掉;
    2)⼀个⼩于127的字符的意义与原来相同,但两个⼤于127的字符连在⼀起时,就 表⽰⼀个汉字;
    3)前⾯的⼀个字节(⾼字节)从0xA1⽤到0xF7,后⾯⼀个字节(低字节)从0xA1 到0xFE,总共可以组合出⼤约7000多个简体汉字;
    4)还把数学符号、罗⻢希腊的字⺟、⽇⽂的假名们都编进去,连在 ASCII ⾥本来就有的数字、标点、字⺟都统统重新编了两个字节⻓的编码,这就是常说的“全⻆” 字符,⽽原来在127号以下的那些就叫“半⻆”字符了;
    ⑥ GBK:
    不再要求汉字的低字节⼀定是127号之后的编码,只要第⼀个字节是⼤于127就 表⽰这是⼀个汉字的开始。包括了 GB2312 的所有内容,同时⼜增加了近20000个 新的汉字(包括繁体字)和符号。 ⑦ GB18030:
    后来少数⺠族也要⽤电脑了,于是我们再扩展,⼜加了很多个新的少数⺠族的 字,GBK 扩成了 GB18030。从此之后,中华⺠族的⽂化就可以在计算机时代中传 承了。
    ⑧ DBCS: 以上的这些中⽂的编码标准被称做 “DBCS”(Double Byte Charecter Set 双字节 字符集)。在DBCS系列标准⾥,最⼤的特点是两字节⻓的汉字字符和⼀字节⻓的 英⽂字符并存于同⼀套编码⽅案⾥。
    ⑨ ANSI:
    在 ANSI 编码下,同⼀个编码值,在不同的编码体系⾥代表不同的符号。在简体 中⽂系统下,ANSI 编码代表 GB2312 编码,在⽇⽂系统下,ANSI 编码代表 JIS 编 码。在 ANSI 编码体系下,要想打开⼀个⽂本⽂件,不但要知道它的编码⽅式,还 要安装有对应编码表,否则就可能⽆法读取或出现乱码。为什么电⼦邮件和⽹⻚都 经常会出现乱码,就是因为信息的提供者可能是⽇⽂的 ANSI 编码体系⽽信息的读 取者可能是中⽂的编码体系,他们对同⼀个⼆进制编码值进⾏解读并显⽰,如果采 ⽤了不同的编码,就会导致乱码。这个问题促使了 unicode 码的诞⽣。
    ⑩ UTF-8:
    UTF-8就是在互联⽹上使⽤最⼴的⼀种unicode的实现⽅式,最⼤的特点,就 是采⽤了⼀种变⻓的编码⽅式。它可以使⽤1~4个字节表⽰⼀个符号,根据不同 的符号⽽变化字节⻓度。编码规则如下: 1、对于单字节的符号,字节的第⼀位设为0,后⾯7位为这个符号的unicode码。 因此对于英语字⺟,UTF-8编码和ASCII码是相同的。 2、对于n字节的符号(n>1),第⼀个字节的前n位都设为1,第n+1位设为0,后 ⾯字节的前两位⼀律设为10。剩下的没有提及的⼆进制位,全部为这个符号的 unicode码。

  2. 什么是乱码:
    个⼈认为,如果在储存或传输过程中,计算机中的信息不能被正常解析,从⽽导 致在信息展⽰的时候出现⽆法被正确理解的情况,可以认为出现了“乱码”。
    常⻅的 乱码有以下⼏种表现形式:
    ①部分中⽂字符能够正常展⽰,另外的中⽂字符被展⽰为⽅框; 多数是由于缺少相应的字体⽀持,例如,新安装完linux之后,如果没有安装图形 界⾯,默认的字符窗⼝其实是没有相应的字体⽀持的。
    ②⼏乎所有字符都不能正常展⽰,许多字符被显⽰为“?”,或者被显⽰为⼀⼤堆不 可理解的古怪字符;这种情况很可能是由于字符编码不配套。

  3. 产⽣乱码的原因:
    字符在计算机中是以⼆进制的⽅式进⾏存储的,⽂本本⾝是不能够标识它使⽤ 的编码⽅式的。即同⼀段⼆进制字节流,可以⽤很多种不同的编码⽅式去解码,然 后根据解码后的结果,在操作系统中按照预定义好的字体进⾏展⽰。
    乱码产⽣的根本原因,⼀是没有使⽤正确的解码规则来解释字节流,⼆是使⽤ 了错误的展⽰字体。实际应⽤当中,编码规则的问题居多。

  4. 插⼊中⽂乱码实战分析-dm插⼊中⽂正常:
    插⼊数据时,客⼾端字符集,操作系统字符集会影响到数据库中⽂数据的保存,导 致insert的中⽂,保存在数据库中成为乱码。
    ⾸先看⼀个中⽂数据插⼊正常的例⼦:
    ① “中国”的编码

    • GB18030:D6D0B9FA共计4个字节 
    • UTF-8:E4B8ADE59BBD共计6个字节 
    

    ② 数据库环境:
    • 数据库安装在中⽂windows系统中,IP地址192.168.1.110
    • 初始化两个实例,⼀个是UTF-8字符集(5236),⼀个是GB18030字 符集(5237)
    ③ 客⼾端环境:
    • linux系统上安装disql客⼾端
    • xshell作为linux服务器的终端 在GB18030和UTF-8库中分别创建⼀张表,客⼾端不限–>
    • create table test(col1 int, col2 varchar2(20));
    ④ UFT-8库成功插⼊中⽂数据操作步骤:
    a.打开linux的xshell,设置系统字符集和xshell字符集

    su – dmdba export LANG=zh_CN.UTF-8 --修改xshell字符集为UTF-8
    

    b.为了了解linux客⼾端和windows库之间数据传输的内容,我们⽤tcpdump命令抓 包;
    c.另外打开⼀个session,⽤root⽤⼾登录,输⼊命令:

     tcpdump tcp -i eth4 -s 0 -w ./target_utf8_utf8_utf8.cap
    

    第⼀个utf8表⽰客⼾端系统字符集、第⼆个utf8表⽰xhell字符集、第三个utf8表⽰数 据库字符集。
    d.登录disql,连接UTF-8库,插⼊⼀条带中⽂的数据:

    cd /opt/dmhs/dmdbms/bin disql SYSDBA/SYSDBA@192.168.1.110:5236 
    	  INSERT INTO TEST VALUES(1,’中国’);
    

    ⑤GB18030库成功插⼊中⽂数据操作步骤:
    a.登录disql,连接GB18030库,插⼊⼀条带中⽂的数据:

    cd /opt/dmhs/dmdbms/bin disql SYSDBA/SYSDBA@192.168.1.110:5237 
    	INSERT INTO TEST VALUES(1,’中国’);
    

    初步结论:
    从以上的测试可以看出 1、在客⼾端字符集不变的情况下,客⼾端发给数据库的中⽂是按照数据 库的字符集进⾏编码的。 2、和数据库所在的操作系统字符集⽆关。
    =========================================================================
    下⾯我们尝试把客⼾端字符集改变⼀下,再次来印证这个结论:
    a.打开linux的xshell,设置系统字符集和xshell字符集:

     su – dmdba export LANG=zh_CN.GBK --修改xshell字符集为GB2312 
    

    b.和上⾯的操作步骤类似,打开tcpdump抓包,登录xshell的disql分别在GB18030 库和UTF-8库插⼊数据。

    最终结论:
    1、不论客⼾端的字符集是什么,客⼾端发给数据库的中⽂都是按照数据库 的字符集进⾏编码的。说的简单点就是:客⼾端给我什么,数据库就保存什 么。
    2、通过抓包分析,数据库是什么编码,客⼾端就会传递什么编码的中⽂, 客⼾端和数据库编码⽅式不同时,需要转码,转码是由客⼾端来完成的。
    3、数据库保存数据的编码,和数据库所在的操作系统⽆关。

  5. 插⼊中⽂乱码实战分析-dm插⼊中⽂乱码:
    前⾯我们把xshell和系统字符集设置成⼀样,那如果不⼀样呢,我们来看⼀个中⽂数据插⼊不正常的例⼦,并尝试分析乱码原因:
    ① 打开linux的xshell,设置系统字符集和xshell字符集

    su – dmdba export LANG=zh_CN.GBK --修改xshell字符集为UTF-8
    

    这⾥linux系统和xshell字符 集设置不兼容 前⾯的讨论,我们把xshell和系统字符集设置成⼀样,那如果不⼀样呢,我们来看⼀个中⽂数据插⼊不正常的例⼦,并尝试分析乱码原因;
    ②登录disql,连接UTF-8库,插⼊⼀条带中⽂的数据:

    INSERT INTO TEST VALUES(1,’中国’);
    

    发现,当xshell的字符集时utf-8,系统的字符集是gbk的时候,出现了乱码,我 们做出如下分析: 1、根据刚才的结论和抓包结果分析,数据在客⼾端的时候就已经是乱码了。
    2、乱码的根源可能是在xshell和系统字符集的不兼容。
    插⼊数据乱码的初步结论:
    xshell先把⽤⼾insert语句的中⽂按照xshell设置的编码⽅式保存,要执⾏插 ⼊语句时,系统会将xshell的编码按照系统编码重新处理,最后按照数据库 端的编码⽅式进⾏转换交给数据库。
    ③ 再把xshell和系统字符集互换⼀下,插⼊数据看看会有什么效果:
    a. 打开linux的xshell,设置系统字符集和xshell字符集:

    su – dmdba export LANG=zh_CN.UTF-8 --修改xshell字符集为GBK 
    

    这⾥linux系统和xshell字符 集设置不兼容 我们再把xshell和系统字符集互换⼀下,插⼊数据看看会有什么效果
    b.登录disql,连接UTF-8库,插⼊⼀条带中⽂的数据:

     INSERT INTO TEST VALUES(1,’中国’);
    

    结果:抓包并没有收到任何插⼊语句。
    结论:
    1、xshell以GBK⽅式编码“中国”:
    2、系统以UTF-8⽅式进⾏解码:
    3、由于数据库编码⽅式也是UTF-8,那么系统以UTF-8⽅式解码后,会直接发 送给数据库,但是D6D0B9不符合UTF-8的编码规则,⽆法完成通信,导致数 据插⼊失败。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值