`
wangyijiangshui
  • 浏览: 83059 次
  • 性别: Icon_minigender_1
  • 来自: 合肥
社区版块
存档分类

Unicode编码规则 及Java实现具体转换

阅读更多

1、Ascii编码 
从0x00-0x7f为ASCII编码字符,共有127个字符 

 

2、Unicode编码 共两个字节表示,16位(65535) 现今已经扩展到20位(1048575) 
从0x0000-0xffff(65535) 0x0000 0000 - 0x000f ffff(1048575) (10FFFF) 
Unicode 标准已扩展到包含多达 1,112,064 个字符最高达到0x10ffff个字符 
增补字符是代码点在 U+10000 至 U+10FFFF 范围之间的字符,也就是那些使用原始的 Unicode 的 16 位设计无法表示的字符。从 U+0000 至 U+FFFF 之间的字符集有时候被称为基本多语言面 (BMP)。因此,每一个 Unicode 字符要么属于 BMP,要么属于增补字符 
但是 
D800-DBff (1024) 高16位 
DC00-DFFF (1024) 低16位 
即:从D800-DFFF的2048的字符为UTF-16编码留用 
所以,实际上Unicode能表示的字符范围为(65535-2048)个字符 
因为后来UNICODE3.0之后,加入大量的中日韩字符,UNICODE编码扩展到20位 
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是一种变长字节编码方式。对于某一个字符的UTF-8编码, 
如果只有一个字节则其最高二进制位为0; 
如果是多字节,其第一个字节从最高位开始,连续的二进制位值为1的个数决定了其编码的位数,其余各字节均以10开头。 
UTF-8最多可用到6个字节。 
UTF-8用于编码UNICODE字符,能编码32位的UNICODE,现今的UNICODE字符的编码范围是0000 0000 --- 000F FFFF(20位) 
所以UTF-8编码可以编码所有的UNICODE字符 
如表: 从上一个结束的范围+1然后在加上x的个数所能表示的最大个数,比如10xxxxxx则最多能表示0011 1111 (3F)个 
1字节 0xxxxxxx (0000 0000 --- 0000 007f) 
2字节 110xxxxx 10xxxxxx (0000 0080 --- 0000 07FF) 
3字节 1110xxxx 10xxxxxx 10xxxxxx (0000 0800 --- 0000 FFFF) 
4字节 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx (0001 0000 --- 001F FFFF) 
5字节 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (0020 0000 --- 03FF FFFF) 
6字节 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx (0400 0000 --- 07FF FFFF) 
因此UTF-8中可以用来表示字符编码的实际位数最多有31位,即上表中x所表示的位。除去那些控制位(每字节开头的10等),这些x表示的位与UNICODE编码是一一对应的,位高低顺序也相同。 
实际将UNICODE转换为UTF-8编码时应先去除高位0,然后根据所剩编码的位数决定所需最小的UTF-8编码位数。 
因此那些ASCII字符集中的字符(UNICODE兼容ASCII)只需要一个字节的UTF-8编码(7个二进制位)便可以表示。 
因为最长只有20位范围的UNICODE编码,所以至今最长的UTF-8表示的字符应该只有4位 
UTF-16 
从编码看UTF-16的编码和UNICODE完全相同.但是使用大于16位(到最高20位)的UNICODE后,则Unicode编码0000-FFFF之间,JAVA中则产生的字节序列加前缀:FEFF我估计如果是用小端机这个值应该是FF FE 
这可能是为了和WINDOWS的记事本中的文本表示方式兼容 
而0001 0000 --- 000F FFFF之间的编码,则要利用到UNICODE编码中的两个特殊段 
第一个两字节需要在这个编码范围:D800-DBFF 之间 
第二个两字节需要在这个编码范围:DC00-DFFF 之间 
在这两段之间,刚好都有10位的位置,所以刚好能表示最长的20位UNICODE字符 。当一个大于0000 FFFF的UNICODE编码 
要使用UTF-16编码UNICODE时。这个UNICODE字符的高10位在D800-DBFF之间即D800|(unicode>>>10) 而低10位则在DC00-DFFF之间,即DC00|(000003FF&unicode) 
虽然如此,但是还是有点小变化。因为编码范围为:0x10000-0x1ffff这之间的0xFFFF个。所以,每一个UNICODE码都必须减去0x10000才是他们事实该用于转化的值。 
例如:UNICODE:0x2A5FE转为utf-16编码应该为: 
int unicode = 0x2A5FE-0x10000;//-0x40 
int utf16 = (((0xd800|((unicode>>10)&0x3ff)))<<16) | (0xdc00|(unicode&0x3ff)); 

UTF-32 
由于暂时UNICODE最多只需要20位来表示,所以UTF-32已经不需要任何变码的形式就能表示所有字符 
所以使用UTF-32来编码UNICODE,可以用非常直接的方式。因此,UTF-32就等于UNICODE编码 
对于编码中提到的关于高位低位的解释: 
我们常使用的X86系列CPU为小端,即:就是低位字节排放在内存的低地址端,高位字节排放在内存的高地址端 
如:数字0x12345678 
地址:0100 0101 0102   0103 
值:     78   56   34     12 
而一些嵌入式的CPU和IBM SUN使用的CPU处理器则使用大端表示的方式,即:高位字节排放在内存的低地址端,低位字节排放在内存的高地址端 
如:数字0x12345678 
地址:0100 0101 0102   0103 
值:     12   34   56     78 
数值的2进制表示方式,从 左----右 表示 高----低 
网络字节序为大端表示法

 

3、Java实现字符到unicode编码的转换:

 

/**
 * native2ascii.exe Java code implementation.
 * 
 * @author
 * @version 1.0
 */
public class Native2AsciiUtils {
	/**
	 * prefix of ascii string of native character
	 */
	private static String PREFIX = "\\u";

	/**
	 * Test
	 * 
	 * @param args
	 */
	public static void main(String[]args) {
		System.out.println(native2Ascii("中国"));
		System.out.println(ascii2Native("\u4e2d\u56fd"));
		System.out.println(String.valueOf("a"));
	}
	
	/**
	 * Native to ascii string. It's same as execut native2ascii.exe.
	 * 
	 * @param str
	 *            native string
	 * @return ascii string
	 */
	public static String native2Ascii(String str) {
		char[] chars = str.toCharArray();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < chars.length; i++) {
			sb.append(char2Ascii(chars[i]));
		}
		return sb.toString();
	}

	/**
	 * Native character to ascii string.
	 * 
	 * @param c
	 *            native character
	 * @return ascii string
	 */
	private static String char2Ascii(char c) {
		if (c > 255) {
			StringBuilder sb = new StringBuilder();
			sb.append(PREFIX);
			int code = (c >> 8);
			String tmp = Integer.toHexString(code);
			if (tmp.length() == 1) {
				sb.append("0");
			}
			sb.append(tmp);
			code = (c & 0xFF);
			tmp = Integer.toHexString(code);
			if (tmp.length() == 1) {
				sb.append("0");
			}
			sb.append(tmp);
			return sb.toString();
		} else {
			return Character.toString(c);
		}
	}

	/**
	 * Ascii to native string. It's same as execut native2ascii.exe -reverse.
	 * 
	 * @param str
	 *            ascii string
	 * @return native string
	 */
	public static String ascii2Native(String str) {
		StringBuilder sb = new StringBuilder();
		int begin = 0;
		int index = str.indexOf(PREFIX);
		while (index != -1) {
			sb.append(str.substring(begin, index));
			sb.append(ascii2Char(str.substring(index, index + 6)));
			begin = index + 6;
			index = str.indexOf(PREFIX, begin);
		}
		sb.append(str.substring(begin));
		return sb.toString();
	}

	/**
	 * Ascii to native character.
	 * 
	 * @param str
	 *            ascii string
	 * @return native character
	 */
	private static char ascii2Char(String str) {
		if (str.length() != 6) {
			throw new IllegalArgumentException(
					"Ascii string of a native character must be 6 character.");
		}
		if (!PREFIX.equals(str.substring(0, 2))) {
			throw new IllegalArgumentException(
					"Ascii string of a native character must start with \"\\u\".");
		}
		String tmp = str.substring(2, 4);
		int code = Integer.parseInt(tmp, 16) << 8;
		tmp = str.substring(4, 6);
		code += Integer.parseInt(tmp, 16);
		return (char) code;
	}
}
 

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics