首先不管是哪种编码都是兼容ASCII码的。
Unicode
Unicode存在着的缺点:
Unicode只是一个符号集, 它只规定了符号的二进制代码, 却没有规定这个二进制代码应该如何存储.
这里就有两个严重的问题:
第一个问题是, 如何才能区别unicode和ascii?计算机怎么知道三个字节表示一个符号, 而不是分别表示三个符号呢?
第二个问题是, 我们已经知道,英文字母只用一个字节表示就够了, 如果unicode统一规定, 每个符号用三个或四个字节表示, 那么每个英文字母前都必然有二到三个字节是0, 这对于存储来说是极大的浪费,文本文件的大小会因此大出二三倍, 这是无法接受的.
Unicode编码则是采用双字节16位来进行编号,可编65536字符,基本上包含了世界上所有的语言字符,它也就成为了全世界一种通用的编码,而且用十六进制4位表示一个编码,非常简结直观,为大多数开发者所接受,特别是十六进制编码后,可以解决汉字在js再编码过程中出现乱码问题,提高解释速度,我们建议在js脚本中使用十六进制unicode编码。
UniCode汉字转换,网上很多,但相对比较好使的比较少,大都写法一样,转换的效果差别不大,或多或少有些遗憾,我这找到个相对较好的,能直接转换标点符号的转换器。
【Unicode 码表】
0000-007F:C0控制符及基本拉丁文 (C0 Control and Basic Latin)0080-00FF:C1控制符及拉丁文补充-1 (C1 Control and Latin 1 Supplement) 0100-017F:拉丁文扩展-A (Latin Extended-A) 0180-024F:拉丁文扩展-B (Latin Extended-B) 0250-02AF:国际音标扩展 (IPA Extensions) 02B0-02FF:空白修饰字母 (Spacing Modifiers) 0300-036F:结合用读音符号 (Combining Diacritics Marks) 0370-03FF:希腊文及科普特文 (Greek and Coptic) 0400-04FF:西里尔字母 (Cyrillic) 0500-052F:西里尔字母补充 (Cyrillic Supplement) 0530-058F:亚美尼亚语 (Armenian) 0590-05FF:希伯来文 (Hebrew) 0600-06FF:阿拉伯文 (Arabic) 0700-074F:叙利亚文 (Syriac) 0750-077F:阿拉伯文补充 (Arabic Supplement) 0780-07BF:马尔代夫语 (Thaana) 07C0-077F:西非書面語言 (N'Ko) 0800-085F:阿维斯塔语及巴列维语 (Avestan and Pahlavi) 0860-087F:Mandaic 0880-08AF:撒马利亚语 (Samaritan) 0900-097F:天城文书 (Devanagari) 0980-09FF:孟加拉语 (Bengali) 0A00-0A7F:锡克教文 (Gurmukhi) 0A80-0AFF:古吉拉特文 (Gujarati) 0B00-0B7F:奥里亚文 (Oriya) 0B80-0BFF:泰米尔文 (Tamil) 0C00-0C7F:泰卢固文 (Telugu) 0C80-0CFF:卡纳达文 (Kannada) 0D00-0D7F:德拉维族语 (Malayalam) 0D80-0DFF:僧伽罗语 (Sinhala) 0E00-0E7F:泰文 (Thai) 0E80-0EFF:老挝文 (Lao) 0F00-0FFF:藏文 (Tibetan) 1000-109F:缅甸语 (Myanmar) 10A0-10FF:格鲁吉亚语 (Georgian) 1100-11FF:朝鲜文 (Hangul Jamo) 1200-137F:埃塞俄比亚语 (Ethiopic) 1380-139F:埃塞俄比亚语补充 (Ethiopic Supplement) 13A0-13FF:切罗基语 (Cherokee) 1400-167F:统一加拿大土著语音节 (Unified Canadian Aboriginal Syllabics) 1680-169F:欧甘字母 (Ogham) 16A0-16FF:如尼文 (Runic) 1700-171F:塔加拉语 (Tagalog) 1720-173F:Hanunóo 1740-175F:Buhid 1760-177F:Tagbanwa 1780-17FF:高棉语 (Khmer) 1800-18AF:蒙古文 (Mongolian) 18B0-18FF:Cham 1900-194F:Limbu 1950-197F:德宏泰语 (Tai Le) 1980-19DF:新傣仂语 (New Tai Lue) 19E0-19FF:高棉语记号 (Kmer Symbols) 1A00-1A1F:Buginese 1A20-1A5F:Batak 1A80-1AEF:Lanna 1B00-1B7F:巴厘语 (Balinese) 1B80-1BB0:巽他语 (Sundanese) 1BC0-1BFF:Pahawh Hmong 1C00-1C4F:雷布查语(Lepcha) 1C50-1C7F:Ol Chiki 1C80-1CDF:曼尼普尔语 (Meithei/Manipuri) 1D00-1D7F:语音学扩展 (Phonetic Extensions) 1D80-1DBF:语音学扩展补充 (Phonetic Extensions Supplement) 1DC0-1DFF:结合用读音符号补充 (Combining Diacritics Marks Supplement) 1E00-1EFF:拉丁文扩充附加 (Latin Extended Additional) 1F00-1FFF:希腊语扩充 (Greek Extended) 2000-206F:常用标点 (General Punctuation) 2070-209F:上标及下标 (Superscripts and Subscripts) 20A0-20CF:货币符号 (Currency Symbols) 20D0-20FF:组合用记号 (Combining Diacritics Marks for Symbols) 2100-214F:字母式符号 (Letterlike Symbols) 2150-218F:数字形式 (Number Form) 2190-21FF:箭头 (Arrows) 2200-22FF:数学运算符 (Mathematical Operator) 2300-23FF:杂项工业符号 (Miscellaneous Technical) 2400-243F:控制图片 (Control Pictures) 2440-245F:光学识别符 (Optical Character Recognition) 2460-24FF:封闭式字母数字 (Enclosed Alphanumerics) 2500-257F:制表符 (Box Drawing) 2580-259F:方块元素 (Block Element) 25A0-25FF:几何图形 (Geometric Shapes) 2600-26FF:杂项符号 (Miscellaneous Symbols) 2700-27BF:印刷符号 (Dingbats) 27C0-27EF:杂项数学符号-A (Miscellaneous Mathematical Symbols-A) 27F0-27FF:追加箭头-A (Supplemental Arrows-A) 2800-28FF:盲文点字模型 (Braille Patterns) 2900-297F:追加箭头-B (Supplemental Arrows-B) 2980-29FF:杂项数学符号-B (Miscellaneous Mathematical Symbols-B) 2A00-2AFF:追加数学运算符 (Supplemental Mathematical Operator) 2B00-2BFF:杂项符号和箭头 (Miscellaneous Symbols and Arrows) 2C00-2C5F:格拉哥里字母 (Glagolitic) 2C60-2C7F:拉丁文扩展-C (Latin Extended-C) 2C80-2CFF:古埃及语 (Coptic) 2D00-2D2F:格鲁吉亚语补充 (Georgian Supplement) 2D30-2D7F:提非纳文 (Tifinagh) 2D80-2DDF:埃塞俄比亚语扩展 (Ethiopic Extended) 2E00-2E7F:追加标点 (Supplemental Punctuation) 2E80-2EFF:CJK 部首补充 (CJK Radicals Supplement) 2F00-2FDF:康熙字典部首 (Kangxi Radicals) 2FF0-2FFF:表意文字描述符 (Ideographic Description Characters) 3000-303F:CJK 符号和标点 (CJK Symbols and Punctuation) 3040-309F:日文平假名 (Hiragana) 30A0-30FF:日文片假名 (Katakana) 3100-312F:注音字母 (Bopomofo) 3130-318F:朝鲜文兼容字母 (Hangul Compatibility Jamo) 3190-319F:象形字注释标志 (Kanbun) 31A0-31BF:注音字母扩展 (Bopomofo Extended) 31C0-31EF:CJK 笔画 (CJK Strokes) 31F0-31FF:日文片假名语音扩展 (Katakana Phonetic Extensions) 3200-32FF:封闭式 CJK 文字和月份 (Enclosed CJK Letters and Months) 3300-33FF:CJK 兼容 (CJK Compatibility) 3400-4DBF:CJK 统一表意符号扩展 A (CJK Unified Ideographs Extension A) 4DC0-4DFF:易经六十四卦符号 (Yijing Hexagrams Symbols) 4E00-9FBF:CJK 统一表意符号 (CJK Unified Ideographs) A000-A48F:彝文音节 (Yi Syllables) A490-A4CF:彝文字根 (Yi Radicals) A500-A61F:Vai A660-A6FF:统一加拿大土著语音节补充 (Unified Canadian Aboriginal Syllabics Supplement) A700-A71F:声调修饰字母 (Modifier Tone Letters) A720-A7FF:拉丁文扩展-D (Latin Extended-D) A800-A82F:Syloti Nagri A840-A87F:八思巴字 (Phags-pa) A880-A8DF:Saurashtra A900-A97F:爪哇语 (Javanese) A980-A9DF:Chakma AA00-AA3F:Varang Kshiti AA40-AA6F:Sorang Sompeng AA80-AADF:Newari AB00-AB5F:越南傣语 (Vi?t Thái) AB80-ABA0:Kayah Li AC00-D7AF:朝鲜文音节 (Hangul Syllables) D800-DBFF:High-half zone of UTF-16 DC00-DFFF:Low-half zone of UTF-16 E000-F8FF:自行使用區域 (Private Use Zone) F900-FAFF:CJK 兼容象形文字 (CJK Compatibility Ideographs) FB00-FB4F:字母表達形式 (Alphabetic Presentation Form) FB50-FDFF:阿拉伯表達形式A (Arabic Presentation Form-A) FE00-FE0F:变量选择符 (Variation Selector) FE10-FE1F:竖排形式 (Vertical Forms) FE20-FE2F:组合用半符号 (Combining Half Marks) FE30-FE4F:CJK 兼容形式 (CJK Compatibility Forms) FE50-FE6F:小型变体形式 (Small Form Variants) FE70-FEFF:阿拉伯表達形式B (Arabic Presentation Form-B) FF00-FFEF:半型及全型形式 (Halfwidth and Fullwidth Form) FFF0-FFFF:特殊 (Specials)
UTF-8 因为Unicode并没有规定二进制代码是如何存储的,所以就出现了很多种实现Unicode存储的方式,UTF-8是在互联网上使用最广的一种unicode的实现方式. 其他实现方式还包括UTF-16和UTF-32, 不过在互联网上基本不用.重复一遍, 这里的关系是, UTF-8是Unicode的实现方式之一.
UTF-8最大的一个特点, 就是它是一种变长的编码方式. 它可以使用1~6个字节表示一个符号, 根据不同的符号而变化字节长度.
UTF-8的编码规则很简单, 只有两条:1) 对于单字节的符号, 字节的第一位设为0, 后面7位为这个符号的unicode码. 因此对于英语字母, UTF-8编码和ASCII码是相同的.2) 对于n字节的符号(n>1),第一个字节的前n位都设为1, 第n+1位设为0, 后面字节的前两位一律设为10. 剩下的没有提及的二进制位, 全部为这个符号的unicode码.
下表总结了编码规则, 字母x表示可用编码的位.
下面, 以汉字"严"为例, 演示如何实现UTF-8编码.已知"严"的unicode是4E25(1001110 00100101), 根据上表, 可以发现4E25处在第三行的范围内(0000 0800 - 0000 FFFF), 因此"严"的UTF-8编码需要三个字节, 即格式是"1110xxxx 10xxxxxx 10xxxxxx". 然后, 从"严"的最后一个二进制位开始, 依次从后向前填入格式中的x, 多出的位补0. 这样就得到了, "严"的UTF-8编码是 "11100100 1011100010100101", 转换成十六进制就是E4B8A5.
Unicode与UTF-8之间的转换
/***************************************************************************** * 将一个字符的Unicode(UCS-2和UCS-4)编码转换成UTF-8编码. * * 参数: * unic 字符的Unicode编码值 * pOutput 指向输出的用于存储UTF8编码值的缓冲区的指针 * outsize pOutput缓冲的大小 * * 返回值: * 返回转换后的字符的UTF8编码所占的字节数, 如果出错则返回 0 . * * 注意: * 1. UTF8没有字节序问题, 但是Unicode有字节序要求; * 字节序分为大端(Big Endian)和小端(Little Endian)两种; * 在Intel处理器中采用小端法表示, 在此采用小端法表示. (低地址存低位) * 2. 请保证 pOutput 缓冲区有最少有 6 字节的空间大小! ****************************************************************************/ int enc_unicode_to_utf8_one(unsigned long unic, unsigned char *pOutput, int outSize) { assert(pOutput != NULL); assert(outSize >= 6); if ( unic <= 0x0000007F ) { // * U-00000000 - U-0000007F: 0xxxxxxx *pOutput = (unic & 0x7F); return 1; } else if ( unic >= 0x00000080 && unic <= 0x000007FF ) { // * U-00000080 - U-000007FF: 110xxxxx 10xxxxxx *(pOutput+1) = (unic & 0x3F) | 0x80; *pOutput = ((unic >> 6) & 0x1F) | 0xC0; return 2; } else if ( unic >= 0x00000800 && unic <= 0x0000FFFF ) { // * U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx *(pOutput+2) = (unic & 0x3F) | 0x80; *(pOutput+1) = ((unic >> 6) & 0x3F) | 0x80; *pOutput = ((unic >> 12) & 0x0F) | 0xE0; return 3; } else if ( unic >= 0x00010000 && unic <= 0x001FFFFF ) { // * U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput+3) = (unic & 0x3F) | 0x80; *(pOutput+2) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput+1) = ((unic >> 12) & 0x3F) | 0x80; *pOutput = ((unic >> 18) & 0x07) | 0xF0; return 4; } else if ( unic >= 0x00200000 && unic <= 0x03FFFFFF ) { // * U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput+4) = (unic & 0x3F) | 0x80; *(pOutput+3) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput+2) = ((unic >> 12) & 0x3F) | 0x80; *(pOutput+1) = ((unic >> 18) & 0x3F) | 0x80; *pOutput = ((unic >> 24) & 0x03) | 0xF8; return 5; } else if ( unic >= 0x04000000 && unic <= 0x7FFFFFFF ) { // * U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx *(pOutput+5) = (unic & 0x3F) | 0x80; *(pOutput+4) = ((unic >> 6) & 0x3F) | 0x80; *(pOutput+3) = ((unic >> 12) & 0x3F) | 0x80; *(pOutput+2) = ((unic >> 18) & 0x3F) | 0x80; *(pOutput+1) = ((unic >> 24) & 0x3F) | 0x80; *pOutput = ((unic >> 30) & 0x01) | 0xFC; return 6; } return 0; } /***************************************************************************** * 将一个字符的UTF8编码转换成Unicode(UCS-2和UCS-4)编码. * * 参数: * pInput 指向输入缓冲区, 以UTF-8编码 * Unic 指向输出缓冲区, 其保存的数据即是Unicode编码值, * 类型为unsigned long . * * 返回值: * 成功则返回该字符的UTF8编码所占用的字节数; 失败则返回0. * * 注意: * 1. UTF8没有字节序问题, 但是Unicode有字节序要求; * 字节序分为大端(Big Endian)和小端(Little Endian)两种; * 在Intel处理器中采用小端法表示, 在此采用小端法表示. (低地址存低位) ****************************************************************************/ int enc_utf8_to_unicode_one(const unsigned char* pInput, unsigned long *Unic) { assert(pInput != NULL && Unic != NULL); // b1 表示UTF-8编码的pInput中的高字节, b2 表示次高字节, ... char b1, b2, b3, b4, b5, b6; *Unic = 0x0; // 把 *Unic 初始化为全零 int utfbytes = enc_get_utf8_size(*pInput); unsigned char *pOutput = (unsigned char *) Unic; switch ( utfbytes ) { case 0: *pOutput = *pInput; utfbytes += 1; break; case 2: b1 = *pInput; b2 = *(pInput + 1); if ( (b2 & 0xE0) != 0x80 ) return 0; *pOutput = (b1 << 6) + (b2 & 0x3F); *(pOutput+1) = (b1 >> 2) & 0x07; break; case 3: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) ) return 0; *pOutput = (b2 << 6) + (b3 & 0x3F); *(pOutput+1) = (b1 << 4) + ((b2 >> 2) & 0x0F); break; case 4: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) ) return 0; *pOutput = (b3 << 6) + (b4 & 0x3F); *(pOutput+1) = (b2 << 4) + ((b3 >> 2) & 0x0F); *(pOutput+2) = ((b1 << 2) & 0x1C) + ((b2 >> 4) & 0x03); break; case 5: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); b5 = *(pInput + 4); if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80) ) return 0; *pOutput = (b4 << 6) + (b5 & 0x3F); *(pOutput+1) = (b3 << 4) + ((b4 >> 2) & 0x0F); *(pOutput+2) = (b2 << 2) + ((b3 >> 4) & 0x03); *(pOutput+3) = (b1 << 6); break; case 6: b1 = *pInput; b2 = *(pInput + 1); b3 = *(pInput + 2); b4 = *(pInput + 3); b5 = *(pInput + 4); b6 = *(pInput + 5); if ( ((b2 & 0xC0) != 0x80) || ((b3 & 0xC0) != 0x80) || ((b4 & 0xC0) != 0x80) || ((b5 & 0xC0) != 0x80) || ((b6 & 0xC0) != 0x80) ) return 0; *pOutput = (b5 << 6) + (b6 & 0x3F); *(pOutput+1) = (b5 << 4) + ((b6 >> 2) & 0x0F); *(pOutput+2) = (b3 << 2) + ((b4 >> 4) & 0x03); *(pOutput+3) = ((b1 << 6) & 0x40) + (b2 & 0x3F); break; default: return 0; break; } return utfbytes; }
名称 Unicode 符号
句号 3002 。
问号 FF1F ?
叹号 FF01 !
逗号 FF0C ,
顿号 3001 、
分号 FF1B ;
冒号 FF1A :
引号 300C 「
300D 」
引号 300E 『
300F 』
引号 2018 ‘
2019 ’
引号 201C “
201D ”
括号 FF08 (
FF09 )
括号 3014 〔
3015 〕
括号 3010 【
3011 】
破折号 2014 —
省略号 2026 …
连接号 2013 –
间隔号 FF0E .
书名号 300A 《
300B 》
书名号 3008 〈
3009 〉
整理后如下:
2013 – 2014 — 2026 … 2018 ‘ 2019 ’ 201C “ 201D ” 3001 、3002 。 3008 〈 3009 〉 300A 《 300B 》 300C 「 300D 」 300E 『 300F 』3010 【 3011 】 3014 〔 3015 〕FF01 ! FF08 ( FF0C ,FF09 ) FF0E . FF1B ; FF1A : FF1F ?
GBK编码
GBK编码采用双字节编码方案,其编码范围:8140-FEFE,剔除xx7F码位,共23940个码位。共收录汉字和图形符号21886个,其中汉字(包括部首和构件)21003个,图形符号883个