1、尚学堂张志宇乱码分析01基础1. 什么是ASCII码ASCII(American Standard Code for Information Interchange,美国信息互换标准代码)ASCII码一共规定了128个字符的编码ASCII 表上的数字 031 分配给了控制字符,用于控制像打印机等一些外围设备。它已被国际标准化组织(ISO)定为国际标准,称为ISO 646标准。参考:从这里看ASCII的内容或者看这张图来了解ASCII的内容控制字符都什么含义,可以从这个网址了解http:/zh.wikipedia.org/w/index.php?title=ASCII&variant=zh-cn
2、2. 什么是ISO/IEC iso8859ISO 8859,全称ISO/IEC 8859,是国际标准化组织(ISO)及国际电工委员会(IEC)联合制定的一系列8位字符集的标准,现时定义了15个字符集。 ISO/IEC 8859-1 (Latin-1) - 西欧语言 ISO/IEC 8859-2 (Latin-2) - 中欧语言 ISO/IEC 8859-3 (Latin-3) - 南欧语言。世界语也可用此字符集显示。 ISO/IEC 8859-4 (Latin-4) - 北欧语言 ISO/IEC 8859-5 (Cyrillic) - 斯拉夫语言 ISO/IEC 8859-6 (Arabic)
3、 - 阿拉伯语 ISO/IEC 8859-7 (Greek) - 希腊语 ISO/IEC 8859-8 (Hebrew) - 希伯来语(视觉顺序) ISO 8859-8-I - 希伯来语(逻辑顺序) ISO/IEC 8859-9 (Latin-5 或 Turkish) - 它把Latin-1的冰岛语字母换走,加入土耳其语字母。 ISO/IEC 8859-10 (Latin-6 或 Nordic) - 北日耳曼语支,用来代替Latin-4。 ISO/IEC 8859-11 (Thai) - 泰语,从泰国的 TIS620 标准字集演化而来。 ISO/IEC 8859-13 (Latin-7 或 B
4、altic Rim) - 波罗的语族 ISO/IEC 8859-14 (Latin-8 或 Celtic) - 凯尔特语族 ISO/IEC 8859-15 (Latin-9) - 西欧语言,加入Latin-1欠缺的芬兰语字母和大写法语重音字母,以及欧元()符号。 ISO/IEC 8859-16 (Latin-10) - 东南欧语言。主要供罗马尼亚语使用,并加入欧元符号。参考:这里有比较详细的说明http:/zh.wikipedia.org/w/index.php?title=ISO/IEC_8859&variant=zh-cn3. ISO/IEC 8859十五个字符集的比较参考http:/zh
5、.wikipedia.org/w/index.php?title=ISO/IEC_8859&variant=zh-cn或者看这个也行http:/www.terena.org/activities/multiling/ml-docs/iso-8859.html4. 什么是iso-8859-1在ISO/IEC 8859-n之中,国际标准化组织只替每个字符集定义了最多96个字符(0xA0-0xFF)。ISO-8859-n(在ISO与8859之间加上一连字号)则是由IANA根据ISO/IEC 8859-n所定义的编码表。它除了ISO/IEC 8859-n的字符外,还包括ASCII(0x20-0x7E)
6、字符及65个控制字符(0x00-0x1F及0x7E-0x9F)。参考:http:/zh.wikipedia.org/wiki/ISO/IEC_8859-15. 什么是unicodeUnicode 的编码方式与 ISO 10646 的通用字符集(Universal Character Set,UCS)概念相对应,目前实际应用的 Unicode 版本对应于 UCS-2,使用16位的编码空间。也就是每个字符占用2个字节。参考:中文的说明http:/zh.wikipedia.org/w/index.php?title=Unicode&variant=zh-cn官方网址http:/www.unicode
7、.org/如果想下载编码具体内容 http:/www.unicode.org/charts/查看各种字符集的对应关系http:/www.unicode.org/Public/MAPPINGS/完整Unicode编码表http:/zh.wikibooks.org/wiki/Unicode6. 增补字符增补字符是 Unicode 标准中代码点超出 U+FFFF 的字符增补字符是代码点在 U+10000 至 U+10FFFF 范围之间的字符,也就是那些使用原始的 Unicode 的 16 位设计无法表示的字符在UTF-16编码中,增补字符表示成两个字节。第一个字节属于高代理范围(uD800-uDBF
8、F), 第二个字节属于低代理范围 (uDC00-uDFFF).package encodetest;public class TestChar public static void main(String args) System.out.println(Character.charCount(0x10000); System.out.println(Character.isHighSurrogate(char)0xd87e); System.out.println(Character.isLowSurrogate(char)0xdc1a); String s=String.valueOf(C
9、haracter.toChars(0x2F81A); charchars=s.toCharArray(); for(char c:chars) System.out.format(%x,(short)c); /d87edc1a /这个字符变成了两个char型变量,其中0xd87e就是高代理部分的值,0xdc1a就是低代理的值。 参考Java 平台中的增补字符7. Big Endian和Little Endian一个字符可能占用多个字节,那么这多个字节在计算机中如何存储呢?比如字符0xabcd,它的存储格式到底是 AB CD,还是 CD AB 呢?实际上两者都有可能,并分别有不同的名字。如果存储
10、为 AB CD,则称为Big Endian;如果存储为 CD AB,则称为Little Endian。8. ISO/IEC 8859-1:1998 与Unicode的关系http:/www.unicode.org/Public/MAPPINGS/ISO8859/8859-1.TXT9. ASCII与Unicode的关系http:/www.unicode.org/Public/MAPPINGS/VENDORS/MISC/US-ASCII-QUOTES.TXT10. UCS-2和UCS-4 Unicode是为整合全世界的所有语言文字而诞生的。任何文字在Unicode中都对应一个值,这个值称为代码点
11、(code point)。代码点的值通常写成 U+ABCD 的格式。而文字和代码点之间的对应关系就是UCS-2(Universal Character Set coded in 2 octets)。顾名思义,UCS-2是用两个字节来表示代码点,其取值范围为 U+0000U+FFFF。 为了能表示更多的文字,人们又提出了UCS-4,即用四个字节表示代码点。它的范围为 U+00000000U+7FFFFFFF,其中 U+00000000U+0000FFFF和UCS-2是一样的。 要注意,UCS-2和UCS-4只规定了代码点和文字之间的对应关系,并没有规定代码点在计算机中如何存储。规定存储方式的称为
12、UTF(Unicode Transformation Format),其中应用较多的就是UTF-16和UTF-8了。11. UTF-16 UTF-16由RFC2781规定,它使用两个字节来表示一个代码点。 不难猜到,UTF-16是完全对应于UCS-2的,即把UCS-2规定的代码点通过Big Endian或Little Endian方式直接保存下来。UTF-16包括三种:UTF-16,UTF-16BE(Big Endian),UTF-16LE(Little Endian)。 UTF-16BE和UTF-16LE不难理解,而UTF-16就需要通过在文件开头以名为BOM(Byte Order Mark
13、)的字符来表明文件是Big Endian还是Little Endian。BOM为U+FEFF这个字符。 其实BOM是个小聪明的想法。由于UCS-2没有定义U+FFFE,因此只要出现 FF FE 或者 FE FF 这样的字节序列,就可以认为它是U+FEFF,并且可以判断出是Big Endian还是Little Endian。 举个例子。“ABC”这三个字符用各种方式编码后的结果如下:UTF-16BE00 41 00 42 00 43UTF-16LE41 00 42 00 43 00UTF-16(Big Endian)FE FF 00 41 00 42 00 43UTF-16(Little End
14、ian)FF FE 41 00 42 00 43 00UTF-16(不带BOM)00 41 00 42 00 43 Windows平台下默认的Unicode编码为Little Endian的UTF-16(即上述的 FF FE 41 00 42 00 43 00)。你可以打开记事本,写上ABC,然后保存,再用二进制编辑器看看它的编码结果。 另外,UTF-16还能表示一部分的UCS-4代码点U+10000U+10FFFF。表示算法比较复杂,简单说明如下: 从代码点U中减去0x10000,得到U。这样U+10000U+10FFFF就变成了 0x000000xFFFFF。 用20位二进制数表示U。 U
15、=yyyyyyyyyyxxxxxxxxxx 将前10位和后10位用W1和W2表示,W1=110110yyyyyyyyyy,W2=110111xxxxxxxxxx,则 W1 = D800DBFF,W2 = DC00DFFF。 例如,U+12345表示为 D8 08 DF 45(UTF-16BE),或者08 D8 45 DF(UTF-16LE)。 但是由于这种算法的存在,造成UCS-2中的 U+D800U+DFFF 变成了无定义的字符。参考:http:/www.ietf.org/rfc/rfc2781.txt12. UTF-32UTF-32用四个字节表示代码点,这样就可以完全表示UCS-4的所有代
16、码点,而无需像UTF-16那样使用复杂的算法。与UTF-16类似,UTF-32也包括UTF-32、UTF-32BE、UTF-32LE三种编码,UTF-32也同样需要BOM字符。仅用ABC举例:UTF-32BE00 00 00 41 00 00 00 42 00 00 00 43UTF-32LE41 00 00 00 42 00 00 00 43 00 00 00UTF-32(Big Endian)00 00 FE FF 00 00 00 41 00 00 00 42 00 00 00 43UTF-32(Little Endian)FF FE 00 00 41 00 00 00 42 00 00
17、 00 43 00 00 00UTF-32(不带BOM)00 00 00 41 00 00 00 42 00 00 00 4313. UTF-8UTF-16和UTF-32的一个缺点就是它们固定使用两个或四个字节,这样在表示纯ASCII文件时会有很多00字节,造成浪费。而RFC3629定义的UTF-8则解决了这个问题。UTF-8用14个字节来表示代码点。表示方式如下:UCS-2 (UCS-4)位序列第一字节第二字节第三字节第四字节U+0000 . U+007F00000000-0xxxxxxx0xxxxxxxU+0080 . U+07FF00000xxx-xxyyyyyy110xxxxx10yy
18、yyyyU+0800 . U+FFFFxxxxyyyy-yyzzzzzz1110xxxx10yyyyyy10zzzzzzU+10000.U+1FFFFF00000000-000wwwxx-xxxxyyyy-yyzzzzzzz11110www10xxxxxx10yyyyyy10zzzzzz可见,ASCII字符(U+0000U+007F)部分完全使用一个字节,避免了存储空间的浪费。而且UTF-8不再需要BOM字节。另外,从上表中可以看出,单字节编码的第一字节为00-7F,双字节编码的第一字节为C2-DF,三字节编码的第一字节为E0-EF。这样只要看到第一个字节的范围就可以知道编码的字节数。这样也可
19、以大大简化算法。14. java和Unicode的关系下面这段话来自JDK文档关于Unicode的说明。Programs are written using the Unicode character set. Information about this character set and its associated character encodings may be found at:http:/www.unicode.orgjava程序是基于Unicode 字符集来编写的。关于这个字符集以及它的相关的编码可以在这个网站找到:http:/www.unicode.orgThe Java
20、platform tracks the Unicode specification as it evolves. The precise version of Unicode used by a given release is specified in the documentation of the class Character.Java平台跟着Unicode的规范而变化。Java的每一个版本用到的准确的Unicode的版本号,定义在Character类的文档中。Versions of the Java programming language prior to 1.1 used Uni
21、code version 1.1.5. Upgrades to newer versions of the Unicode Standard occurred in JDK 1.1 (to Unicode 2.0), JDK 1.1.7 (to Unicode 2.1), J2SE 1.4 (to Unicode 3.0), and J2SE 5.0 (to Unicode 4.0).Java 1.1用的是Unicode 1.1.5。JDK 1.1 用的是Unicode 2.0, JDK 1.1.7 用的是Unicode 2.1, J2SE 1.4用的是Unicode 3.0, and J2S
22、E 5.0 用的是Unicode 4.0。(J2SE 6.0 用的也是Unicode 4.0)The Unicode standard was originally designed as a fixed-width 16-bit character encoding. It has since been changed to allow for characters whose representation requires more than 16 bits. The range of legal code points is now U+0000 to U+10FFFF, using t
23、he hexadecimal U+n notation. Characters whose code points are greater than U+FFFF are called supplementary characters. To represent the complete range of characters using only 16-bit units, the Unicode standard defines an encoding called UTF-16. In this encoding, supplementary characters are represe
24、nted as pairs of 16-bit code units, the first from the high-surrogates range, (U+D800 to U+DBFF), the second from the low-surrogates range (U+DC00 to U+DFFF). For characters in the range U+0000 to U+FFFF, the values of code points and UTF-16 code units are the same.Unicode标准最初的设计是16位固定宽度的字符编码. 后来变为允
25、许用多于16位来表示字符。现在的合法的代码点从U+0000 to U+10FFFF, 16进制的表示方式。代码点大于U+FFFF 的字符叫做补充字符. 为了只用16位来表示全部范围的字符, Unicode标准定义了一套编码,叫做UTF-16. 在这个编码中,补充字符被表示为2个16-bit编码, 第一部分编码的范围是(U+D800 to U+DBFF), 第二部分编码的范围是 (U+DC00 to U+DFFF). 对于在 U+0000 to U+FFFF范围的字符来说, 代码点的值和UTF-16编码是一致的。Java编程语言用16位的编码代表文本。使用UTF-16编码. 少数的APIs, 主
26、要在Character 类中,用32-bit 的整数来代表代码点的单个实例。Java平台提供方法在两种表示方法之间进行转换。This book uses the terms code point and UTF-16 code unit where the representation is relevant, and the generic term character where the representation is irrelevant to the discussion.J2SE 技术规范现在使用术语代码点和 UTF-16 代码单元(表示法是相关的)以及通用术语字符(表示法与该讨
27、论没有关系)。(API 通常使用名称 codePoint 描述表示代码点的类型 int 的变量,而 UTF-16 代码单元的类型当然为 char。)Except for comments (3.7), identifiers, and the contents of character and string literals (3.10.4, 3.10.5), all input elements (3.5) in a program are formed only from ASCII characters (or Unicode escapes (3.3) which result in
28、ASCII characters). ASCII (ANSI X3.4) is the American Standard Code for Information Interchange. The first 128 characters of the Unicode character encoding are the ASCII characters.除了注释,标识符,字符常量,字符串常量,程序里其他的所有的输入元素只能是ASCII字符(或者通过转义得到的ASCII字符)。ASCII (ANSI X3.4) 是美国信息互换标准代码. Unicode字符编码中的前128个字符就是ASCII
29、字符。下面这段话来自API的关于java.lang.Character类的描述。The set of characters from U+0000 to U+FFFF is sometimes referred to as the Basic Multilingual Plane (BMP). Characters whose code points are greater than U+FFFF are called supplementary characters. The Java 2 platform uses the UTF-16 representation in char arr
30、ays and in the String and StringBuffer classes. In this representation, supplementary characters are represented as a pair of char values, the first from the high-surrogates range, (uD800-uDBFF), the second from the low-surrogates range (uDC00-uDFFF).范围是U+0000 到 U+FFFF 的字符,指的是Basic Multilingual Plane (BMP). 代码点比 U+FFFF 还大的字符叫增补字符. Java 2 平台在char arrays 和String 和 StringBuffer 类中使用UTF-16编码。在这种编码中,增补字符表示成两个char的值。第一个char的属于高代理范围(uD800-uDBFF), 第二个char属于低代理范围 (uDC00-uDFFF).参考:JDK文档关于Unicode的说明:15. char的含义
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1