欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Java在多线程IO操作环境下如何高效的将Byte(二进制)数组转换成String以及根据位置获取其字符

程序员文章站 2022-04-29 15:54:13
...

 

      本博客属原创文章,欢迎转载!转载请务必注明出处:http://guoyunsky.iteye.com/blog/854730

     

欢迎加入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的作用,对于底层也没多少经验.欢迎大家指教!很感谢!

 

 

更多技术文章、感悟、分享、勾搭,请用微信扫描:

Java在多线程IO操作环境下如何高效的将Byte(二进制)数组转换成String以及根据位置获取其字符
            
    
    博客分类: java Java多线程QQluceneSolr