java中 unicode编码问题 unicodejava编码扩展 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 你查看下API就清楚了;再有是了解下UTF-16编码的规则,如BE和LE的区别;也可测试下:前面的两个字节其实是FE FF,表示高字节在前; 忘说是 查看Character类;示例下:public class CharacterDemo { public static void main(String[] args) throws IOException { String str = "我"; for(int i=0;i<str.length();i++){ Character ch = str.charAt(i); System.out.println(ch+" "+ch.SIZE+" "+String.valueOf(ch).getBytes("UNICODE").length); System.out.println(byteToHex(String.valueOf(ch).getBytes("UNICODE"))); } } public static String byteToHex(byte [] bytes){ StringBuilder sb = new StringBuilder(4); for (int b : bytes) { sb.append(Integer.toHexString(b & 0x00FF | 0xFF00).substring(2, 4).toUpperCase()); sb.append(" "); } return sb.toString(); }} CharsetEncoder 中 544行 cr = encodeLoop(in, out);要被执行,根据前面得到的判断结果,应该回去执行 class UTF_16 extends Unicode中的方法 private static class Encoder extends UnicodeEncoder { public Encoder(Charset charset) { super(charset, 0, true); } }我想问一下 从 encodeLoop()-------> Encoder函数 这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行public abstract class UnicodeEncoder extends CharsetEncoder 中的方法 protected UnicodeEncoder(Charset charset, int i, boolean flag) { super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] { -3, -1 }) : (new byte[] { -1, -3 })); usesMark = needsMark = flag; byteOrder = i; }中完成 为毛 jdk源码中没有 sun.nio.cs.UnicodeEncoder 的源码? CharsetEncoder 中 544行 cr = encodeLoop(in, out);要被执行,根据前面得到的判断结果,应该回去执行 class UTF_16 extends Unicode中的方法 private static class Encoder extends UnicodeEncoder { public Encoder(Charset charset) { super(charset, 0, true); } }我想问一下 从 encodeLoop()-------> Encoder函数 这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行public abstract class UnicodeEncoder extends CharsetEncoder 中的方法 protected UnicodeEncoder(Charset charset, int i, boolean flag) { super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] { -3, -1 }) : (new byte[] { -1, -3 })); usesMark = needsMark = flag; byteOrder = i; }中完成我对源代码的态度是:找关键的看,有目的的看,看得懂就看;你上面说的源代码在sun开头的包中,而sun开头的包是不包含在JDK自带的那个src.zip中的;你需要自己去下载;或下载个反编译的工具也是可以的;至于你上面说的源代码不明白,也简单说下:其实你不需要关心UnicodeEncoder这个构造器方法;关键就是上面提到的 encodeLoop(in, out),这个方法才是关键的;这里有个参数 in 和 out,那其实简化就是in表示输入,out表示要输出的(out是ByteBuffer,in是CharBufer,从参数类型也可以看出);而且你也知道在CharsetEncoder类中,encodeLoop是protected abstract的,那自然是子类实现了; 你找到了UTF_16,但它是Charset的子类,但它定义了一个内部类 Encoder extends UnicodeEncoder ,而UnicodeEncoder有个encodeLoop() ,看到这里其它的可以忽略了吧,直接查看UnicodeEncoder 的 encodeLoop(); 如果是反编译的话,你会看到UnicodeEncoder 的 put方法是这样: private void put(char paramChar, ByteBuffer paramByteBuffer) { if (this.byteOrder == 0) { paramByteBuffer.put((byte)(paramChar >> '\b')); paramByteBuffer.put((byte)(paramChar & 0xFF)); } else { paramByteBuffer.put((byte)(paramChar & 0xFF)); paramByteBuffer.put((byte)(paramChar >> '\b')); } }它的encodeLoop方法前面是这样的:protected CoderResult encodeLoop(CharBuffer paramCharBuffer, ByteBuffer paramByteBuffer) { int i = paramCharBuffer.position(); if (this.needsMark) { if (paramByteBuffer.remaining() < 2) return CoderResult.OVERFLOW; put(65279, paramByteBuffer); this.needsMark = false; } try {... ....看到这里,需要考虑下那个needsMark, 你上面提到的UTF_16 类中的内部类Encoder 会 super(charset, 0, true); 而这个needsMark = flag; 所以很显然是true了;由于编译器对于一些常量是内嵌的,反编译后那个put方法了有点难理解,但可以自己动手测试下就清楚了:如:byte[] b1 = {((byte)(65279 >> '\b'))}; byte[] b2 = {((byte)(65279 & 0xFF))}; System.out.print(byteToHex(b1) + ' '); System.out.print(byteToHex(b2)); System.out.println(); byte[] b11 = {((byte)('我' >> '\b'))}; byte[] b22 = {((byte)('我' & 0xFF))}; System.out.print(byteToHex(b11) + ' '); System.out.print(byteToHex(b22)); System.out.println();其实put方法中的:if (this.byteOrder == 0) 表示的是高字节在前的意思;如果你是附加源代码的方式查看,那就非常的明确了; CharsetEncoder 中 544行 cr = encodeLoop(in, out);要被执行,根据前面得到的判断结果,应该回去执行 class UTF_16 extends Unicode中的方法 private static class Encoder extends UnicodeEncoder { public Encoder(Charset charset) { super(charset, 0, true); } }我想问一下 从 encodeLoop()-------> Encoder函数 这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行public abstract class UnicodeEncoder extends CharsetEncoder 中的方法 protected UnicodeEncoder(Charset charset, int i, boolean flag) { super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] { -3, -1 }) : (new byte[] { -1, -3 })); usesMark = needsMark = flag; byteOrder = i; }中完成当然,如果你纠结于此,可以看下StringCoding的内部类StringEncoder 的 encode方法: static byte[] encode(String charsetName, char[] ca, int off, int len) throws UnsupportedEncodingException { StringEncoder se = (StringEncoder)deref(encoder); String csn = (charsetName == null) ? "ISO-8859-1" : charsetName; if ((se == null) || !(csn.equals(se.requestedCharsetName()) || csn.equals(se.charsetName()))) { se = null; try { Charset cs = lookupCharset(csn); if (cs != null) se = new StringEncoder(cs, csn); } catch (IllegalCharsetNameException x) {} if (se == null) throw new UnsupportedEncodingException (csn); set(encoder, se); } return se.encode(ca, off, len); }当调用new StringEncoder(cs, csn)时,就会调用初始化 Charset 的 Encoder --> cs.newEncoder();这样很清楚了吧; Container.remove(Component comp) 方法的用法求助 送分帖 有没有进行算术运算的API啊,进行积分或者LOG运算 IIS6.0+Tomact5.0怎样配置? 有几个问题请教,100分! 请问用iText组件用java生成pdf文件时,中文全是问好,是怎么回事? 请哪位高手赐教一个比较概念的东西 Jbuilder5中的jTable简单问题,20分!!! 线程死锁问题 Java 正则表达式匹配出来 放进JAVA容器?? java 怎样将网页中选中的文字复制到剪贴板? java多线程读取文件夹中的多个文件问题,新手多谢!
再有是了解下UTF-16编码的规则,如BE和LE的区别;也可测试下:前面的两个字节其实是FE FF,表示高字节在前;
for(int i=0;i<str.length();i++){
Character ch = str.charAt(i);
System.out.println(ch+" "+ch.SIZE+" "+String.valueOf(ch).getBytes("UNICODE").length);
System.out.println(byteToHex(String.valueOf(ch).getBytes("UNICODE")));
}
}
public static String byteToHex(byte [] bytes){
StringBuilder sb = new StringBuilder(4);
for (int b : bytes) {
sb.append(Integer.toHexString(b & 0x00FF | 0xFF00).substring(2, 4).toUpperCase());
sb.append(" ");
}
return sb.toString(); }
}
private static class Encoder extends UnicodeEncoder
{ public Encoder(Charset charset)
{
super(charset, 0, true);
}
}我想问一下 从 encodeLoop()-------> Encoder函数 这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行
public abstract class UnicodeEncoder extends CharsetEncoder 中的方法 protected UnicodeEncoder(Charset charset, int i, boolean flag)
{
super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] {
-3, -1
}) : (new byte[] {
-1, -3
}));
usesMark = needsMark = flag;
byteOrder = i;
}
中完成
private static class Encoder extends UnicodeEncoder
{ public Encoder(Charset charset)
{
super(charset, 0, true);
}
}我想问一下 从 encodeLoop()-------> Encoder函数 这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行
public abstract class UnicodeEncoder extends CharsetEncoder 中的方法 protected UnicodeEncoder(Charset charset, int i, boolean flag)
{
super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] {
-3, -1
}) : (new byte[] {
-1, -3
}));
usesMark = needsMark = flag;
byteOrder = i;
}
中完成
我对源代码的态度是:找关键的看,有目的的看,看得懂就看;你上面说的源代码在sun开头的包中,而sun开头的包是不包含在JDK自带的那个src.zip中的;你需要自己去下载;或下载个反编译的工具也是可以的;至于你上面说的源代码不明白,也简单说下:
其实你不需要关心UnicodeEncoder这个构造器方法;
关键就是上面提到的 encodeLoop(in, out),这个方法才是关键的;
这里有个参数 in 和 out,那其实简化就是in表示输入,out表示要输出的(out是ByteBuffer,in是CharBufer,从参数类型也可以看出);而且你也知道在CharsetEncoder类中,encodeLoop是protected abstract的,那自然是子类实现了;
你找到了UTF_16,但它是Charset的子类,但它定义了一个内部类 Encoder extends UnicodeEncoder ,而UnicodeEncoder有个encodeLoop() ,看到这里其它的可以忽略了吧,直接查看UnicodeEncoder 的 encodeLoop();
如果是反编译的话,你会看到UnicodeEncoder 的 put方法是这样:
private void put(char paramChar, ByteBuffer paramByteBuffer) {
if (this.byteOrder == 0) {
paramByteBuffer.put((byte)(paramChar >> '\b'));
paramByteBuffer.put((byte)(paramChar & 0xFF));
} else {
paramByteBuffer.put((byte)(paramChar & 0xFF));
paramByteBuffer.put((byte)(paramChar >> '\b'));
} }它的encodeLoop方法前面是这样的:
protected CoderResult encodeLoop(CharBuffer paramCharBuffer, ByteBuffer paramByteBuffer)
{
int i = paramCharBuffer.position(); if (this.needsMark) {
if (paramByteBuffer.remaining() < 2)
return CoderResult.OVERFLOW;
put(65279, paramByteBuffer); this.needsMark = false;
}
try
{
... ....
看到这里,需要考虑下那个needsMark, 你上面提到的UTF_16 类中的内部类Encoder 会 super(charset, 0, true); 而这个needsMark = flag; 所以很显然是true了;
由于编译器对于一些常量是内嵌的,反编译后那个put方法了有点难理解,但可以自己动手测试下就清楚了:
如:
byte[] b1 = {((byte)(65279 >> '\b'))};
byte[] b2 = {((byte)(65279 & 0xFF))};
System.out.print(byteToHex(b1) + ' ');
System.out.print(byteToHex(b2));
System.out.println();
byte[] b11 = {((byte)('我' >> '\b'))};
byte[] b22 = {((byte)('我' & 0xFF))};
System.out.print(byteToHex(b11) + ' ');
System.out.print(byteToHex(b22));
System.out.println();
其实put方法中的:if (this.byteOrder == 0) 表示的是高字节在前的意思;如果你是附加源代码的方式查看,那就非常的明确了;
private static class Encoder extends UnicodeEncoder
{ public Encoder(Charset charset)
{
super(charset, 0, true);
}
}我想问一下 从 encodeLoop()-------> Encoder函数 这之间是不是还有别的操作,这两个函数的参数个数也不一样啊--------------------------------------------------------根据源码,貌似最后一定回去执行
public abstract class UnicodeEncoder extends CharsetEncoder 中的方法 protected UnicodeEncoder(Charset charset, int i, boolean flag)
{
super(charset, 2.0F, flag ? 4F : 2.0F, i != 0 ? (new byte[] {
-3, -1
}) : (new byte[] {
-1, -3
}));
usesMark = needsMark = flag;
byteOrder = i;
}
中完成
当然,如果你纠结于此,可以看下StringCoding的内部类StringEncoder 的 encode方法:
static byte[] encode(String charsetName, char[] ca, int off, int len)
throws UnsupportedEncodingException
{
StringEncoder se = (StringEncoder)deref(encoder);
String csn = (charsetName == null) ? "ISO-8859-1" : charsetName;
if ((se == null) || !(csn.equals(se.requestedCharsetName())
|| csn.equals(se.charsetName()))) {
se = null;
try {
Charset cs = lookupCharset(csn);
if (cs != null)
se = new StringEncoder(cs, csn);
} catch (IllegalCharsetNameException x) {}
if (se == null)
throw new UnsupportedEncodingException (csn);
set(encoder, se);
}
return se.encode(ca, off, len);
}当调用new StringEncoder(cs, csn)时,就会调用初始化 Charset 的 Encoder --> cs.newEncoder();
这样很清楚了吧;