'java字符串是有char序列组成。'问:这个命题是否成立?
常用的Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。
代码单元是什么?代码点是什么?
public static void main(String[] args) {
String str = "中文aA";
for(int i=0;;){
if(i<str.length()){
int cp = str.codePointAt(i);
System.out.println((char)cp +"--"+ cp);
if(Character.isSupplementaryCodePoint(cp)){
i += 2;
}else{
i += 1;
}
}else{
break;
}
}
}
运行结果:
中--20013
文--25991
a--97
A--6541在什么情况下表示A?
常用的Unicode字符使用一个代码单元就可以表示,而辅助字符需要一对代码单元表示。
代码单元是什么?代码点是什么?
public static void main(String[] args) {
String str = "中文aA";
for(int i=0;;){
if(i<str.length()){
int cp = str.codePointAt(i);
System.out.println((char)cp +"--"+ cp);
if(Character.isSupplementaryCodePoint(cp)){
i += 2;
}else{
i += 1;
}
}else{
break;
}
}
}
运行结果:
中--20013
文--25991
a--97
A--6541在什么情况下表示A?
code unit:特定的比特序列具体:
http://en.wikipedia.org/wiki/Code_point
你看到的
中--20013
文--25991
a--97
A--65数字就是表示的这些被占的位置(编号)
代码单元是跟具体编码方式相关的概念,比如UTF-32,就是用固定的32位(3字节)作为一个代码单元,而UTF-8则是用1个字节~6个字节作为一个代码单元,因为不定长,所以必须有些约定,如3字节的时候,一定是1110 XXXX 10XX XXXX 10XX XXXX ,实际可用的位数为4+6+6=16位,相当于2个字节。汉字在UTF-8里面是3字节,比如“中”,代码位是20013,那么16进制是0x4E2D,二进制是100111000101101
你把这16位对应插入前面的X上,就是“中”的UTF-8码了。
比如UTF-32,就是用固定的32位(3字节)作为一个代码单元。这句是不是有点问题?
最后,再次谢谢指点。
代码点的话未必是16进制,它只是可以用16进制来表示。
Code Point: Any value in the Unicode codespace; that is, the range of integers from 0x0 to 0x10FFFF. unicode codespace中的一个值。Code Unit: The minimal bit combination that can represent a unit of encoded text for processing or interchange. The Unicode Standard uses 8-bit code units in the UTF-8 encoding form, 16-bit code units in the UTF-16 encoding form, and 32-bit code units in the UTF-32 encoding form. (See definition D28a in Section 3.9, Unicode Encoding Forms.) 一个可以为所表示的编码文本起处理和交换作用的最小比特组合。http://blogs.msdn.com/b/michkap/archive/2005/08/12/451043.aspxWith US-ASCII, code unit is 7 bits.
With UTF-8, code unit is 8 bits.
With EBCDIC, code unit is 8 bits.
With UTF-16, code unit is 16 bits.
With UTF-32, code unit is 32 bits.
拿U8来举例,code unit是8bit,也就是一个字节,但是中文的‘中’2进制表示是:100111000101101(15位,前面补0,就是16位,两个字节),难道是说这‘中’字是由两个code unit组成的?是这个意思吗?
像US-ASCII, code unit is 7 bits. 是7位也是对的
[Java code]
package com.catmiw.csdn;import java.io.UnsupportedEncodingException;public class CharacterSetTest {
public static void main(String[] args) throws UnsupportedEncodingException {
String str="中";
int codepoint=str.codePointAt(0);
System.out.println("'"+str+"'的UNICODE编号(编码点,Unicode code point)="+codepoint+"[0x"+Integer.toHexString(codepoint)+"]");
System.out.println();
byte[] bytes=str.getBytes("utf32");
System.out.println("'中'的UTF-32编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("utf16");
System.out.println("'中'的UTF-16编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("UTF-16BE");
System.out.println("'中'的UTF-16BE编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("UTF-16LE");
System.out.println("'中'的UTF-16LE编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("utf8");
System.out.println("'中'的UTF-8编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
byte b=bytes[0];
System.out.println("3字节UTF8的第1个字节:"+toBinaryString(b)+"[1110xxxx]");
b=bytes[1];
System.out.println("3字节UTF8的第2个字节:"+toBinaryString(b)+"[10xxxxxx]");
b=bytes[2];
System.out.println("3字节UTF8的第3个字节:"+toBinaryString(b)+"[10xxxxxx]");
bytes=str.getBytes("GBK");
System.out.println("'中'的gbk编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("GB2312");
System.out.println("'中'的GB2312编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("US-ASCII");
System.out.println("'中'的US-ASCII编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("ISO-8859-1");
System.out.println("'中'的ISO-8859-1编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes)+",可以看出被丢了一半");
System.out.println();
str="A";
bytes=str.getBytes("utf32");
System.out.println("'A'的UTF-32编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("utf16");
System.out.println("'A'的UTF-16编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("UTF-16BE");
System.out.println("'A'的UTF-16BE编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("UTF-16LE");
System.out.println("'A'的UTF-16LE编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("utf8");
System.out.println("'A'的UTF-8编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("GBK");
System.out.println("'A'的gbk编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
bytes=str.getBytes("GB2312");
System.out.println("'A'的GB2312编码单元长度为:"+bytes.length+",内容为:"+toHexString(bytes));
System.out.println();
byte[] bytes2={0x4E,0x2D};
String str2=new String(bytes2,"UTF-16");
System.out.println("从0x4E2D 按UTF-16 转出来的:"+str2); byte[] bytes4={(byte)0xfe,(byte)0xff,0x4E,0x2D};
String str4=new String(bytes4,"UTF-16");
System.out.println("从0xFEFF4E2D 按UTF-16 转出来的:"+str4); byte[] bytes3={(byte) 0xE4,(byte) 0xB8,(byte) 0xAD};
String str3=new String(bytes3,"UTF8");
System.out.println("从0xE4B8AD 按UTF-8 转出来的:"+str3); } public static String toBinaryString(byte b){
StringBuilder sb=new StringBuilder("");
String temp=Integer.toBinaryString(b&0xff);
sb.append("00000000".substring(temp.length())).append(temp);
return sb.toString();
}
public static String toHexString(byte[] bytes){
StringBuilder sb=new StringBuilder("0x");
for (int i=0;i<bytes.length;i++){
String temp=Integer.toHexString(bytes[i]&0xff);
sb.append((temp.length()==1)?"0"+temp:temp);
}
return sb.toString();
}
}[/Java code]
1.“就是用固定的32位(3字节)作为一个代码单元”下面已提出
2.“UTF-8则是用1个字节~6个字节作为一个代码单元“
UTF-8依据代码点数值可以包含1-4个代码单元 每个代码单元8位
UTF-32每个字符不管代码点值为何 只包含一个代码单元 每个代码单元32位
以此类推
以下为测试例子public class Test
{
public static void main(String[] args)
{
String s = "hello\uD840\uDC00";
int b = s.length();
int n = s.codePointCount(0, s.length());
char f = s.charAt(4);
char l = s.charAt(6);
int index=s.offsetByCodePoints(0,4);
int cp=s.codePointAt(index);
System.out.println(cp);
System.out.println(f);
System.out.println(l);
System.out.println(b);
System.out.println(n);
}
}可参考java核心技术 卷1 3.35