精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-12-29
最后修改:2011-06-20
本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/854730 本博客已迁移到本人独立博客: http://www.yun5u.com/ 欢迎加入Heritrix群(QQ): 109148319 , 10447185 , Lucene/Solr群(QQ) : 118972724 慢慢的得开始考虑些底层的东西,以前微乎其微的一个小功能或许在今天就足已影响你程序的性能、效率等问题.就如现在碰到的,将一个Byte数组,转换成字符串,并且还可以动态的根据位置获取该位置的字符.如果在以往,可能简单的借用String几个方法就行.但换到今天,不得不考虑效率的问题. 这是我总结出来的一个转换类,也参考了开源机器爬虫Heritrix,主要借用Java的NIO来实现.代码和测试类如下: import java.io.Closeable; import java.io.UnsupportedEncodingException; import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.Charset; import org.archive.io.CharSubSequence; /** * @contributor guoyun */ public class ByteArrayToCharBufferAndString implements CharSequence,Closeable{ private CharBuffer charBuffer=null; public static final String DEFAULT_ENCODING="ISO8859_1"; /** * @param buffer byte数组 * @param start 开始位置 * @param size 长度 * @param encoding 编码 */ public ByteArrayToCharBufferAndString(byte[] buffer,long start,long size,String encoding){ super(); charBuffer=byteArrayToCharBuffer(buffer,start,size,encoding); } private CharBuffer byteArrayToCharBuffer(byte[] buffer,long start,long size,String encoding){ ByteBuffer bb=ByteBuffer.wrap(buffer); bb.position((int)start); bb.limit((int)size); Charset charset=null; try { charset=Charset.forName(encoding); } catch (RuntimeException e) { charset=Charset.forName(DEFAULT_ENCODING); } return charset.decode(bb).asReadOnlyBuffer(); } @Override public char charAt(int index) { return this.charBuffer==null?null:this.charBuffer.charAt(index); } @Override public int length() { return this.charBuffer==null?0:this.charBuffer.limit(); } @Override public CharSequence subSequence(int start, int end) { return new CharSubSequence(this, start, end); } @Override public void close() { if(this.charBuffer!=null){ this.charBuffer.clear(); this.charBuffer=null; } } @Override public String toString() { StringBuffer sb = new StringBuffer(length()); sb.append(this); return sb.toString(); } /** * @param args * @throws UnsupportedEncodingException */ public static void main(String[] args) throws UnsupportedEncodingException { //String str="123456789abcdefghijklmnopqrstuvwxyz"; String str="我宣布,中华人民共和国,成立了!中华人民共和国,从此站起来了!"; byte[] buffer=str.getBytes("UTF-8"); ByteArrayToCharBufferAndString test=null; try { test=new ByteArrayToCharBufferAndString(buffer,0,buffer.length,"UTF-8"); System.out.println("转换成String:"+test.toString()); System.out.println("长度:"+test.length()); System.out.println("获取字符,位置5:"+test.charAt(5)+",位置15:"+test.charAt(15)); } catch (Exception e) { e.printStackTrace(); }finally{ if(test!=null){ test.close(); } } } }
补充:本类只适用于与多线程IO操作环境下.如获取某个端口数据(传统的Socket请求响应)、IO.对于非以上环境这个类反而如有朋友说的那样,反而是浪费了.之前提到说借用NIO,所以没做这个说明. 这里借用网络爬虫打一个比方.爬虫一般一个URL对应一个线程去获取该URL资源.每个URL都从服务器的响应流里面读取字节到以上的byte数组.如果不采用NIO,则线程会一直等在读取字节流上面,影响性能.同时,每读取完一次byte数组就转换成String,则会产生垃圾,转换的String对象不能循环利用(String是final类型).所以以上这个类的作用就出来了,获取服务器响应字节流的时候,没有了线程等待.同时对获取到了的数据用该类包装后,该类对象还可以循环利用. 我也刚刚见识NIO的作用,对于底层也没多少经验.欢迎大家指教!很感谢! 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-12-29
没看懂你的这个类,是用来干啥的。
要是想把byte[]变成字符串,直接用new String(byteArray,charsetName)这样不好吗? |
|
返回顶楼 | |
发表时间:2010-12-29
同样想不通LZ写的这个类比直接new String(bs,charsetName)有啥好处.
性能又没提高 使用还不方便 还定义没必要的close方法 gdpglc 写道 没看懂你的这个类,是用来干啥的。
要是想把byte[]变成字符串,直接用new String(byteArray,charsetName)这样不好吗? |
|
返回顶楼 | |
发表时间:2010-12-30
public static String substring(int start,int end,String str)
{ byte[] bs =str.getBytes(); return new String(bs,start,end-start); } 真的需要这么复杂吗?上面的不行? |
|
返回顶楼 | |
发表时间:2010-12-30
public static void main(String[] args) throws UnsupportedEncodingException { // String str="123456789abcdefghijklmnopqrstuvwxyz"; String str = "我宣布,中华人民共和国,成立了!中华人民共和国,从此站起来了!"; byte[] buffer = str.getBytes("UTF-8"); ByteArrayToCharBufferAndString test = null; try { long start = System.nanoTime(); test = new ByteArrayToCharBufferAndString(buffer, 0, buffer.length, "UTF-8"); // System.out.println("转换成String:"+test.toString()); test.toString(); // System.out.println("长度:"+test.length()); test.length(); // System.out.println("获取字符,位置5:"+test.charAt(5)+",位置15:"+test.charAt(15)); test.charAt(5); test.charAt(15); System.out.println(System.nanoTime() - start); } catch (Exception e) { e.printStackTrace(); } finally { if (test != null) { test.close(); } } long start = System.nanoTime(); String s = new String(buffer, "UTF-8"); s.toString(); s.length(); s.charAt(5); s.charAt(15); System.out.println(System.nanoTime() - start); } 这样测了一下,结果: 1365876 不知道高效在什么地方,还是我的理解有误,请指教 |
|
返回顶楼 | |
发表时间:2010-12-30
dyllove98 写道 public static String substring(int start,int end,String str)
{ byte[] bs =str.getBytes(); return new String(bs,start,end-start); } 真的需要这么复杂吗?上面的不行? +1 |
|
返回顶楼 | |
发表时间:2010-12-30
xrtracker 写道
public static void main(String[] args) throws UnsupportedEncodingException { // String str="123456789abcdefghijklmnopqrstuvwxyz"; String str = "我宣布,中华人民共和国,成立了!中华人民共和国,从此站起来了!"; byte[] buffer = str.getBytes("UTF-8"); ByteArrayToCharBufferAndString test = null; try { long start = System.nanoTime(); test = new ByteArrayToCharBufferAndString(buffer, 0, buffer.length, "UTF-8"); // System.out.println("转换成String:"+test.toString()); test.toString(); // System.out.println("长度:"+test.length()); test.length(); // System.out.println("获取字符,位置5:"+test.charAt(5)+",位置15:"+test.charAt(15)); test.charAt(5); test.charAt(15); System.out.println(System.nanoTime() - start); } catch (Exception e) { e.printStackTrace(); } finally { if (test != null) { test.close(); } } long start = System.nanoTime(); String s = new String(buffer, "UTF-8"); s.toString(); s.length(); s.charAt(5); s.charAt(15); System.out.println(System.nanoTime() - start); } 这样测了一下,结果: 1365876 不知道高效在什么地方,还是我的理解有误,请指教 +1 |
|
返回顶楼 | |
发表时间:2010-12-30
呵呵,谢谢各位的回复.我做了下补充!具体请看底下红色字体部分...
|
|
返回顶楼 | |
发表时间:2010-12-31
没必要吧,直接开多线程去读每个url就可以了。在每个具体的线程中阻塞获取
|
|
返回顶楼 | |
发表时间:2010-12-31
不知道LZ能否提供个你的NIO方法与String的性能对比数据,因为你有这样的环境,所以给个对比
|
|
返回顶楼 | |