zoukankan      html  css  js  c++  java
  • 编码问题总结

      从学编程开始到现在公司写业务,总是被一些莫名的加密和编码折磨的死去活来,而且它们总是混在一起出现在你的面前,将你打不知所措。

    今天,特地抽空理一理他们之前的联系与区别:

      

    为什要用Base64?

    Base64主要用于将不可打印的字符转换成可打印字符,或者简单的说将二进制数据编码成ASCII字符。

    将二进制数据编码成ASCII字符主要的目的是能在纯文本内容中插入二进制数据,常见的应用场景包括:

    1. 电子邮件

      这个可参考阮一峰的《MIME笔记》

    2. 微软的MHT格式

      这是模仿邮件格式将多种资源打包在一个文件中的格式,所有二进制资源都采用 Base64 编码。

    3. XML文件

      这是一个纯文本文件,如果要基于 XML 格式设计可以保存图片或其它附件的数据格式,那就需要将这些二进制数据转码成 ASCII 字符。

    4. DATA URL

      最近流行起来的 Data URL,要在URL中使用二进制数据,当然也只能进行 ASCII 编码

    当然除了 Base64 之外,还有其它一些编码方式可以将二进制数据编码成 ASCII 字符,比如十六进制编码,除此之外还有 Quoted-printable 等。甚至 URL 中使用 %XX 来对非 ASCII 字符进行编码的方式也可以算在内。

    当然一般非特定环境下,选用十六进制编码和 Base64 编码的情况比较多,主要是因为这两种编码易用,而且转换后的数据量相对较小。

    十六进制编码是将 1 个字节编码成 2 个十六进制字符,比如 0x10110110 编码成 B6,转换后数据量会增大 1 倍

    Base64 编码是将 3 个字节共 24 位数据,以每 6 位一个 Base64 字符 [0-9a-zA-Z+/] 表示,24 位数据共需要 4 个 Base64 字符表示,编码后数据增长约 1/3。为什么是“约”?因为如果原数据字节数不是 3 的倍数,需要补位,这样转换出来的数据量就会比原来的 4/3 略多一点。

    从上面的数据增长比来看,Base64编码 比十六进制编码更节省磁盘容量,所以一般较大的数据需要进行 ASCII 编码多采用 Base64;而较小的数据,则使用易于人工识别十六进制(用纸笔就能解码出来)。

    注:data:image/jpg;base64,/9j/  base64转图片的时候貌似总是/9j开头

    上文中提到的Data URL是什么?

    Data URI scheme是在RFC2397中定义的,目的是将一些小的数据,直接嵌入到网页中,从而不用再从外部文件载入。

    优点:减少http连接数。

    缺点:这种格式的文件不会被浏览器缓存。

    不建议将“超过20KB”的文件编码使用,太大的文件反而起反作用。


    data: URI的基本使用格式如下:

    data:[<MIME-type>][;base64|charset=some_charset],<data>
    mime-type是嵌入数据的mime类型,比如png图片就是image/png。
    如果后面跟base64,说明后面的data是采用base64方式进行编码的

    Data URI scheme支持的类型有:
    data:,文本数据
    data:text/plain,文本数据
    data:text/html,HTML代码
    data:text/html;base64,base64编码的HTML代码
    data:text/css,CSS代码
    data:text/css;base64,base64编码的CSS代码
    data:text/JavaScript,Javascript代码
    data:text/javascript;base64,base64编码的Javascript代码
    data:image/gif;base64,base64编码的gif图片数据
    data:image/png;base64,base64编码的png图片数据
    data:image/jpeg;base64,base64编码的jpeg图片数据
    data:image/x-icon;base64,base64编码的icon图片数据

    Unicode与UTF-8,UTF-16,GBK...有什么联系?

       1、Unicode是一种编码规范,是为解决全球字符通用编码而设计的,而rUTF-8,UTF-16等是这种规范的一种实现。

       2、java内部采用Unicode编码规范,也就是支持多语言的,具体采用的UTF-16编码方式。

       3、不管程序过程中用到了gbk,iso8859-1等格式,在存储与传递的过程中实际传递的都是Unicode编码的数据,要想接收到的值不出现乱码,就要保证传过去的时候用的是A编码,接收的时候也用A编码来转换接收。

       4、如果双方的file.encoding确保都相同,那就省事了,都默认转了,但往往在不同项目交互时很多时候是不一致的,这个时候是必须要进行编码转换的。

       5、无论如论转换,java程序的数据都是要先和Unicode做转换,这样也就是能处理多语言字符集的原因了。底层保持了一致,只要在传值和接值的时候也一致就肯定不会出现乱码了。

      注:有人产生疑问,UTF-8 既然能保存那么多文字、符号,为什么国内还有这么多使用 GBK 等编码的人?因为 UTF-8 等编码体积比较大,占电脑空间比较多,如果面向的使用人群绝大部分都是中国人,

      用 GBK 等编码也可以。但是目前的电脑来看,硬盘都是白菜价,电脑性能也已经足够无视这点性能的消耗了。所以推荐所有的网页使用统一编码:UTF-8

      unicode常见的格式如:u4F60u597D...

    UTF-8最大的一个特点,就是它是一种变长的编码方式。它可以使用1~4个字节表示一个符号,根据不同的符号而变化字节长度。

    UTF-8的编码规则很简单,只有二条:

    1)对于单字节的符号,字节的第一位设为0,后面7位为这个符号的unicode码。因此对于英语字母,UTF-8编码和ASCII码是相同的。

    2)对于n字节的符号(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10。剩下的没有提及的二进制位,全部为这个符号的unicode码。

    下表总结了编码规则,字母x表示可用编码的位。

    Unicode符号范围 | UTF-8编码方式
    (十六进制) | (二进制)
    --------------------+---------------------------------------------
    0000 0000-0000 007F | 0xxxxxxx
    0000 0080-0000 07FF | 110xxxxx 10xxxxxx
    0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
    0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

    跟据上表,解读UTF-8编码非常简单。如果一个字节的第一位是0,则这个字节单独就是一个字符;

    如果第一位是1,则连续有多少个1,就表示当前字符占用多少个字节。

    可以看到最多一共有21个x,所以刚好能够表示Unicode的最大的码位。

    下面,还是以汉字"严"为例,演示如何实现UTF-8编码。

    已知"严"的unicode是4E25(100111000100101),根据上表,可以发现4E25处在第三行的范围内(0000 0800-0000 FFFF),因此"严"的UTF-8编码需要三个字节,

    即格式是"1110xxxx 10xxxxxx 10xxxxxx"。然后,从"严"的最后一个二进制位开始,依次从后向前填入格式中的x,多出的位补0。这样就得到了,

    "严"的UTF-8编码是"11100100 10111000 10100101",转换成十六进制就是E4B8A5。

    JAVA中的Unicode如何与其他编码转换呢?

    public class Demo {
    
        public static void main(String args[])throws Exception {
    
            String str = "中文字符";
    
            System.out.println("original string---" + str);// 会正常输出原始串
    
            /**
    
             * str.getBytes();//如果括号中不写charset,则采用的是Sytem.getProperty("file.encoding"),即当前文件的编码方式,
    
             * 很多人写的是系统的默认编码,通过代码测试并非如此,实际得到的是文件的编码方式
    
             *
    
             * str.getBytes("charset");//指定charset,即将底层存储的Unicode码解析为charset编码格式的字节数组方式
    
             *
    
             * String new_str=new String(str.getBytes("utf-8"),"gbk"));
    
             * //将已经由utf-8编码的字节数据转化为gbk解码格式的字符串,在内存中即为gbk格式的字节数组转为Unicode去交互
    
             */
    
            String new_str = new String(str.getBytes("utf-8"), "gbk");
    
            /**
    
             * 此时的输出是乱码,在UTF-8的file.encoding下输出gbk格式的数据肯定是乱码,但是new_str的确是gbk编码式的
    
             * 此时的乱码源于encoding不符,但gbk格式的new_str本身数据并没有问题,通过下面的转换也可以看得出来
    
             */
    
            System.out.println("new string----" + new_str);
    
            String final_str = new String(new_str.getBytes("gbk"), "utf-8");//此处的含意与最上边的注释是一致的参数含意
    
            /**
    
             *输出是正常的,此时将gbk编码格式的new_str字符串,用gbk这个charset去解析它,然后用utf-8再转码一次,
    
             因为new_str确实是gbk格式的,才能经过utf-8编码得到正常的数据显示。
    
             */
    
            System.out.println("final string---"+final_str);
    
        }
    
    }

     http传输时,为什么要对url进行编码?

    1.url有规范,在参数值中出现&字符会截断参数
    2.url中文的问题,编码会转换为英文
    3.也是第一种情况,url中有个参数值是url。传输的时候会出现错误

    Url编码的原则就是使用安全的字符(没有特殊用途或者特殊意义的可打印字符)去表示那些不安全的字符。 哪些字符需要编码 RFC3986文档规定,Url中只允许包含英文字母(a-zA-Z)、数字(0-9)、-_.~4个特殊字符以及所有保留字符。 RFC3986文档对Url的编解码问题做出了详细的建议,指出了哪些字符需要被编码才不会引起Url语义的转变,以及对为什么这些字符需要编码做出了相应的解释。 US-ASCII字符集中没有对应的可打印字符 Url中只允许使用可打印字符。US-ASCII码中的10-7F字节全都表示控制字符,这些字符都不能直接出现在Url中。同时,对于80-FF字节(ISO-8859-1),由于已经超出了US-ACII定义的字节范围,因此也不可以放在Url中。

     需要注意的是,对于Url中的合法字符,编码和不编码是等价的,但是对于上面提到的这些字符,如果不经过编码,那么它们有可能会造成Url语义的不同。因此对于Url而言,只有普通英文字符和数字,特殊字符$-_.+!*’()还有保留字符,才能出现在未经编码的Url之中。其他字符均需要经过编码之后才能出现在Url中。

    --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

                                                       以下转自:http://blog.csdn.net/zhenyu5211314/article/details/51537778

    Unicode字符编码表

    十进制 十六进制  字符数 编码分类(中文) 编码分类(英文)
    起始 终止 起始 终止 (个)    
    0 127 0000 007F 128 C0控制符及基本拉丁文 C0 Control and Basic Latin
    128 255 0080 00FF 128 C1控制符及拉丁文补充-1 C1 Control and Latin 1 Supplement
    256 383 0100 017F 128 拉丁文扩展-A Latin Extended-A
    384 591 0180 024F 208 拉丁文扩展-B Latin Extended-B
    592 687 0250 02AF 96 国际音标扩展 IPA Extensions
    688 767 02B0 02FF 80 空白修饰字母 Spacing Modifiers
    768 879 0300 036F 112 结合用读音符号 Combining Diacritics Marks
    880 1023 0370 03FF 144 希腊文及科普特文 Greek and Coptic
    1024 1279 0400 04FF 256 西里尔字母 Cyrillic
    1280 1327 0500 052F 48 西里尔字母补充 Cyrillic Supplement
    1328 1423 0530 058F 96 亚美尼亚语 Armenian
    1424 1535 0590 05FF 112 希伯来文 Hebrew
    1536 1791 0600 06FF 256 阿拉伯文 Arabic
    1792 1871 0700 074F 80 叙利亚文 Syriac
    1872 1919 0750 077F 48 阿拉伯文补充 Arabic Supplement
    1920 1983 0780 07BF 64 马尔代夫语 Thaana
    1984 2047 07C0 07FF 64 西非書面語言 N'Ko
    2048 2143 0800 085F 96 阿维斯塔语及巴列维语 Avestan and Pahlavi
    2144 2175 0860 087F 32 Mandaic Mandaic
    2176 2223 0880 08AF 48 撒马利亚语 Samaritan
    2304 2431 0900 097F 128 天城文书 Devanagari
    2432 2559 0980 09FF 128 孟加拉语 Bengali
    2560 2687 0A00 0A7F 128 锡克教文 Gurmukhi
    2688 2815 0A80 0AFF 128 古吉拉特文 Gujarati
    2816 2943 0B00 0B7F 128 奥里亚文 Oriya
    2944 3071 0B80 0BFF 128 泰米尔文 Tamil
    3072 3199 0C00 0C7F 128 泰卢固文 Telugu
    3200 3327 0C80 0CFF 128 卡纳达文 Kannada
    3328 3455 0D00 0D7F 128 德拉维族语 Malayalam
    3456 3583 0D80 0DFF 128 僧伽罗语 Sinhala
    3584 3711 0E00 0E7F 128 泰文 Thai
    3712 3839 0E80 0EFF 128 老挝文 Lao
    3840 4095 0F00 0FFF 256 藏文 Tibetan
    4096 4255 1000 109F 160 缅甸语 Myanmar
    4256 4351 10A0 10FF 96 格鲁吉亚语 Georgian
    4352 4607 1100 11FF 256 朝鲜文 Hangul Jamo
    4608 4991 1200 137F 384 埃塞俄比亚语 Ethiopic
    4992 5023 1380 139F 32 埃塞俄比亚语补充 Ethiopic Supplement
    5024 5119 13A0 13FF 96 切罗基语 Cherokee
    5120 5759 1400 167F 640 统一加拿大土著语音节 Unified Canadian Aboriginal Syllabics
    5760 5791 1680 169F 32 欧甘字母 Ogham
    5792 5887 16A0 16FF 96 如尼文 Runic
    5888 5919 1700 171F 32 塔加拉语 Tagalog
    5920 5951 1720 173F 32 Hanunóo Hanunóo
    5952 5983 1740 175F 32 Buhid Buhid
    5984 6015 1760 177F 32 Tagbanwa Tagbanwa
    6016 6143 1780 17FF 128 高棉语 Khmer
    6144 6319 1800 18AF 176 蒙古文 Mongolian
    6320 6399 18B0 18FF 80 Cham Cham
    6400 6479 1900 194F 80 Limbu Limbu
    6480 6527 1950 197F 48 德宏泰语 Tai Le
    6528 6623 1980 19DF 96 新傣仂语 New Tai Lue
    6624 6655 19E0 19FF 32 高棉语记号 Kmer Symbols
    6656 6687 1A00 1A1F 32 Buginese Buginese
    6688 6751 1A20 1A5F 64 Batak Batak
    6784 6895 1A80 1AEF 112 Lanna Lanna
    6912 7039 1B00 1B7F 128 巴厘语 Balinese
    7040 7088 1B80 1BB0 49 巽他语 Sundanese
    7104 7167 1BC0 1BFF 64 Pahawh Hmong Pahawh Hmong
    7168 7247 1C00 1C4F 80 雷布查语 Lepcha
    7248 7295 1C50 1C7F 48 Ol Chiki Ol Chiki
    7296 7391 1C80 1CDF 96 曼尼普尔语 Meithei/Manipuri
    7424 7551 1D00 1D7F 128 语音学扩展 Phonetic Extensions
    7552 7615 1D80 1DBF 64 语音学扩展补充 Phonetic Extensions Supplement
    7616 7679 1DC0 1DFF 64 结合用读音符号补充 Combining Diacritics Marks Supplement
    7680 7935 1E00 1EFF 256 拉丁文扩充附加 Latin Extended Additional
    7936 8191 1F00 1FFF 256 希腊语扩充 Greek Extended
    8192 8303 2000 206F 112 常用标点 General Punctuation
    8304 8351 2070 209F 48 上标及下标 Superscripts and Subscripts
    8352 8399 20A0 20CF 48 货币符号 Currency Symbols
    8400 8447 20D0 20FF 48 组合用记号 Combining Diacritics Marks for Symbols
    8448 8527 2100 214F 80 字母式符号 Letterlike Symbols
    8528 8591 2150 218F 64 数字形式 Number Form
    8592 8703 2190 21FF 112 箭头 Arrows
    8704 8959 2200 22FF 256 数学运算符 Mathematical Operator
    8960 9215 2300 23FF 256 杂项工业符号 Miscellaneous Technical
    9216 9279 2400 243F 64 控制图片 Control Pictures
    9280 9311 2440 245F 32 光学识别符 Optical Character Recognition
    9312 9471 2460 24FF 160 封闭式字母数字 Enclosed Alphanumerics
    9472 9599 2500 257F 128 制表符 Box Drawing
    9600 9631 2580 259F 32 方块元素 Block Element
    9632 9727 25A0 25FF 96 几何图形 Geometric Shapes
    9728 9983 2600 26FF 256 杂项符号 Miscellaneous Symbols
    9984 10175 2700 27BF 192 印刷符号 Dingbats
    10176 10223 27C0 27EF 48 杂项数学符号-A Miscellaneous Mathematical Symbols-A
    10224 10239 27F0 27FF 16 追加箭头-A Supplemental Arrows-A
    10240 10495 2800 28FF 256 盲文点字模型 Braille Patterns
    10496 10623 2900 297F 128 追加箭头-B Supplemental Arrows-B
    10624 10751 2980 29FF 128 杂项数学符号-B Miscellaneous Mathematical Symbols-B
    10752 11007 2A00 2AFF 256 追加数学运算符 Supplemental Mathematical Operator
    11008 11263 2B00 2BFF 256 杂项符号和箭头 Miscellaneous Symbols and Arrows
    11264 11359 2C00 2C5F 96 格拉哥里字母 Glagolitic
    11360 11391 2C60 2C7F 32 拉丁文扩展-C Latin Extended-C
    11392 11519 2C80 2CFF 128 古埃及语 Coptic
    11520 11567 2D00 2D2F 48 格鲁吉亚语补充 Georgian Supplement
    11568 11647 2D30 2D7F 80 提非纳文 Tifinagh
    11648 11743 2D80 2DDF 96 埃塞俄比亚语扩展 Ethiopic Extended
    11776 11903 2E00 2E7F 128 追加标点 Supplemental Punctuation
    11904 12031 2E80 2EFF 128 CJK 部首补充 CJK Radicals Supplement
    12032 12255 2F00 2FDF 224 康熙字典部首 Kangxi Radicals
    12272 12287 2FF0 2FFF 16 表意文字描述符 Ideographic Description Characters
    12288 12351 3000 303F 64 CJK 符号和标点 CJK Symbols and Punctuation
    12352 12447 3040 309F 96 日文平假名 Hiragana
    12448 12543 30A0 30FF 96 日文片假名 Katakana
    12544 12591 3100 312F 48 注音字母 Bopomofo
    12592 12687 3130 318F 96 朝鲜文兼容字母 Hangul Compatibility Jamo
    12688 12703 3190 319F 16 象形字注释标志 Kanbun
    12704 12735 31A0 31BF 32 注音字母扩展 Bopomofo Extended
    12736 12783 31C0 31EF 48 CJK 笔画 CJK Strokes
    12784 12799 31F0 31FF 16 日文片假名语音扩展 Katakana Phonetic Extensions
    12800 13055 3200 32FF 256 封闭式 CJK 文字和月份 Enclosed CJK Letters and Months
    13056 13311 3300 33FF 256 CJK 兼容 CJK Compatibility
    13312 19903 3400 4DBF 6592 CJK 统一表意符号扩展 A CJK Unified Ideographs Extension A
    19904 19967 4DC0 4DFF 64 易经六十四卦符号 Yijing Hexagrams Symbols
    19968 40895 4E00 9FBF 20928 CJK 统一表意符号 CJK Unified Ideographs
    40960 42127 A000 A48F 1168 彝文音节 Yi Syllables
    42128 42191 A490 A4CF 64 彝文字根 Yi Radicals
    42240 42527 A500 A61F 288 Vai Vai
    42592 42751 A660 A6FF 160 统一加拿大土著语音节补充 Unified Canadian Aboriginal Syllabics Supplement
    42752 42783 A700 A71F 32 声调修饰字母 Modifier Tone Letters
    42784 43007 A720 A7FF 224 拉丁文扩展-D Latin Extended-D
    43008 43055 A800 A82F 48 Syloti Nagri Syloti Nagri
    43072 43135 A840 A87F 64 八思巴字 Phags-pa
    43136 43231 A880 A8DF 96 Saurashtra Saurashtra
    43264 43391 A900 A97F 128 爪哇语 Javanese
    43392 43487 A980 A9DF 96 Chakma Chakma
    43520 43583 AA00 AA3F 64 Varang Kshiti Varang Kshiti
    43584 43631 AA40 AA6F 48 Sorang Sompeng Sorang Sompeng
    43648 43743 AA80 AADF 96 Newari Newari
    43776 43871 AB00 AB5F 96 越南傣语 Vi?t Thái
    43904 43936 AB80 ABA0 33 Kayah Li Kayah Li
    44032 55215 AC00 D7AF 11184 朝鲜文音节 Hangul Syllables
    55296 56319 D800 DBFF 1024 High-half zone of UTF-16 High-half zone of UTF-16
    56320 57343 DC00 DFFF 1024 Low-half zone of UTF-16 Low-half zone of UTF-16
    57344 63743 E000 F8FF 6400 自行使用區域 Private Use Zone
    63744 64255 F900 FAFF 512 CJK 兼容象形文字 CJK Compatibility Ideographs
    64256 64335 FB00 FB4F 80 字母表達形式 Alphabetic Presentation Form
    64336 65023 FB50 FDFF 688 阿拉伯表達形式A Arabic Presentation Form-A
    65024 65039 FE00 FE0F 16 变量选择符 Variation Selector
    65040 65055 FE10 FE1F 16 竖排形式 Vertical Forms
    65056 65071 FE20 FE2F 16 组合用半符号 Combining Half Marks
    65072 65103 FE30 FE4F 32 CJK 兼容形式 CJK Compatibility Forms
    65104 65135 FE50 FE6F 32 小型变体形式 Small Form Variants
    65136 65279 FE70 FEFF 144 阿拉伯表達形式B Arabic Presentation Form-B
    65280 65519 FF00 FFEF 240 半型及全型形式 Halfwidth and Fullwidth Form
    65520 65535 FFF0 FFFF 16 特殊 Specials
     
    UTF-8有点类似于Haffman编码,它将Unicode编码为:
    0x00-0x7F的字符,用单个字节来表示;
    0x80-0x7FF的字符用两个字节表示;
    0x800-0xFFFF的字符用3字节表示;
    汉字的unicode范围是:0x4E00~0x9FA5(CJK 统一表意符号)
    其实这个范围还包括了中,日,韩的字符。
     

    大端(BE)和小端(LE)

    考虑4个字节的16进制表示ox12345678,计算机都是以字节为单位存储数据的,因此内存地址空间从低到高被挖成一个个“坑”,

    一个萝卜一个坑,那么相邻的萝卜之间自然就有顺序的问题。文字说明太抽象,直接看图理解。

    大端跟我们平时的书写习惯一致,比较好理解,记住大端就可以了,我们平时说的网络字节顺序也是指大端,至于小端就让它见鬼去吧。

    实在要文字说明理解的话,可以这么来:大端可以认为是“高位在尾端”(大->高),“高位”指的是我们书写时的高位,比如1024,个十百千,1是高位,

    “尾端”指的是内存空间中低地址一端,所以1存储在低地址空间,只不过计算机是以一个字节为单位的。反之小端就是“低位在尾端”(小->低)了。

    BOM

    BOM(Byte Order Mark)是用来区分字节序列和编码方式的(UTF-8,UTF-16,UTF-32)。就是让编辑器或程序读到前面几个字节就知道后面该以哪种编码方式来解析,

    8/16/32是指以多少位作为编码单位的,依次就是1/2/4个字节,因为UTF-8是以单个字节作为编码单位的所以其实没有必要指定它的字节序列,所以UTF-8有BOM和无BOM的两种。

    UTF编码 Byte Order Mark (BOM)
    UTF-8 without BOM
    UTF-8 with BOM EF BB BF
    UTF-16LE FF FE
    UTF-16BE FE FF
    UTF-32LE FF FE 00 00
    UTF-32BE 00 00 FE FF

  • 相关阅读:
    自定义IP原来如此简单
    [转]如何在NIOS II中读写EPCS剩余空间
    坏了的芯片居然又好了一片,太神奇了
    今天报废两片EP3C5E144
    Quartus II 订购版 v10.1 正式推出下载
    发现用JTAG下载程序到EPCS比用AS方式下载速度快
    如何解决No EPCS layout data looking for section [EPCSXXXXXX]
    QII丰衣足食
    Why does my Cyclone III FPGA fail to access the EPCS device using the EPCS Controller module?
    <转载>在.NET中基于Windows消息的IPC实现
  • 原文地址:https://www.cnblogs.com/cangqiongbingchen/p/6196996.html
Copyright © 2011-2022 走看看