`
guoyunsky
  • 浏览: 859790 次
  • 性别: Icon_minigender_1
  • 来自: 上海
博客专栏
3d3a22a0-f00f-3227-8d03-d2bbe672af75
Heritrix源码分析
浏览量:207330
Group-logo
SQL的MapReduce...
浏览量:0
社区版块
存档分类
最新评论

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

    博客分类:
  • java
阅读更多

 

      本博客属原创文章,欢迎转载!转载请务必注明出处: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的作用,对于底层也没多少经验.欢迎大家指教!很感谢!

 

 

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

分享到:
评论
10 楼 guoyunsky 2011-01-04  
onlylau 写道
不知道LZ能否提供个你的NIO方法与String的性能对比数据,因为你有这样的环境,所以给个对比


到时我写
9 楼 onlylau 2010-12-31  
不知道LZ能否提供个你的NIO方法与String的性能对比数据,因为你有这样的环境,所以给个对比
8 楼 borland 2010-12-31  
没必要吧,直接开多线程去读每个url就可以了。在每个具体的线程中阻塞获取
7 楼 guoyunsky 2010-12-30  
呵呵,谢谢各位的回复.我做了下补充!具体请看底下红色字体部分...
6 楼 lardern 2010-12-30  
<div class="quote_title">xrtracker 写道</div>
<div class="quote_div">
<pre name="code" class="java">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);
}</pre>
<p> 这样测了一下,结果:</p>
<p>1365876<br>72947</p>
<p>不知道高效在什么地方,还是我的理解有误,请指教</p>
</div>
<p>+1</p>
5 楼 applepaihs 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
4 楼 xrtracker 2010-12-30  
<pre name="code" class="java">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);
}</pre>
<p> 这样测了一下,结果:</p>
<p>1365876<br>72947</p>
<p>不知道高效在什么地方,还是我的理解有误,请指教</p>
3 楼 dyllove98 2010-12-30  
public static String substring(int start,int end,String str)
  {
byte[] bs =str.getBytes();
return new String(bs,start,end-start);
  }

真的需要这么复杂吗?上面的不行?
2 楼 NanguoCoffee 2010-12-29  
同样想不通LZ写的这个类比直接new String(bs,charsetName)有啥好处.

性能又没提高
使用还不方便
还定义没必要的close方法


gdpglc 写道
没看懂你的这个类,是用来干啥的。
要是想把byte[]变成字符串,直接用new String(byteArray,charsetName)这样不好吗?

1 楼 gdpglc 2010-12-29  
没看懂你的这个类,是用来干啥的。
要是想把byte[]变成字符串,直接用new String(byteArray,charsetName)这样不好吗?

相关推荐

    Java二进制IO类与文件复制操作实例

    本教程将深入探讨Java中的二进制IO类,并通过一个具体的文件复制操作实例来展示它们的应用。 1. **二进制流基础** - Java中的二进制流主要分为两类:字节流和字符流。字节流处理单个字节的数据,而字符流处理...

    C#串口通讯_十六进制转换_数据先进先出原理_委托_单多线程DEMO

    C#提供了多种方法进行转换,如`BitConverter.ToString(byte[])`可以将字节数组转换为十六进制字符串,而`Convert.ToInt32(hexString, 16)`则能将十六进制字符串转换为整数。在串口通信中,可能需要将接收到的字节...

    java的IO流操作

    ### Java的IO流操作 #### 一、Java IO流概述 在Java中,输入/输出(Input/Output,简称IO)流是进行数据读写的基础技术。Java的IO流主要包含两大类:字节流(byte stream)和字符流(character stream)。字节流...

    java io流PPT课件.pptx

    Java IO流是Java编程语言中用于处理输入输出操作的核心组件,尤其在文件操作、设备交互以及数据传输方面扮演着重要角色。在Java中,IO流的概念首次被引入是为了方便数据在不同源和目的地之间流动,它将各种I/O操作...

    Io框架与类图

    本文将深入探讨IO框架,并通过类图解析其内部结构和主要组件,以帮助理解如何在实际应用中有效地使用IO流。 首先,IO框架分为两大类别:字符流(Character Stream)和字节流(Byte Stream)。字符流主要用于处理...

    java io读取文件

    下面我们将深入探讨Java IO读取文件的技术及其在大数据场景下的应用。 1. **基础概念** - **流(Stream)**:Java IO基于流的概念,流是一组有序的数据序列,可以是字节流或字符流。数据从源(如文件)流向目的地...

    java File类字节流(复制、删除、剪切,下载)操作,多线程

    在本主题中,我们将深入探讨`File`类结合字节流如何实现文件和目录的操作,特别是复制、删除、剪切(重命名)以及多线程环境下的文件下载。 首先,让我们来看看`File`类的一些核心方法: 1. `createNewFile()`:...

    java读取纯真IP数据库QQwry.dat的源代码--获取ip所在地区

    这个文件是二进制格式的,由多个记录组成,每个记录包含IP地址范围和对应的地理位置信息。在Java中,我们需要使用`RandomAccessFile`类来处理这种类型的文件,因为它支持随机访问和读取文件中的特定位置。 以下是一...

    JAVA_字节流和字符流

    - Java NIO(New IO)引入了选择器(Selector)和通道(Channel)的概念,允许在一个单独的线程中管理多个输入/输出流,实现高效的I/O多路复用。 在实际编程中,根据数据类型和需求选择合适的流,例如,处理文本...

    Java IO流几种经典使用方式

    ### Java IO流几种经典使用方式 #### 一、输入输出流(Input/Output Stream) ...这段示例代码展示了如何使用`BufferedReader`和`BufferedWriter`来读取和写入文件,体现了Java IO流在实际应用中的灵活性和高效性。

    【IT十八掌徐培成】Java基础第10天-01.字节集-编解码操作-中繁体-StringBuffer.zip

    总的来说,这个课程将帮助学习者掌握Java中关于字节集、编解码和字符串处理的核心概念,特别是对于处理中文繁体字符和多线程环境下的字符串操作,提供了实用的指导。通过理论学习和实践操作,能有效提升Java编程技能...

    io流详解,字符流和字节流代码

    在Java编程语言中,IO(Input/Output)流是一组用于处理输入输出操作的类和接口,它们允许程序与...实践中,你需要根据实际需求选择合适的流类型,合理使用缓冲、转换和多线程通信等功能,以实现高效、灵活的数据传输。

    十进制txt转到bin文件

    在IT领域,转换数据格式是常见的操作之一,例如将文本文件转换为二进制文件。在本案例中,我们关注的是如何使用C#编程语言将包含十进制数字的文本文件(.txt)转换为二进制文件(.bin)。这个过程涉及到读取文本文件...

    Java实现文件复制,File文件读取,写入,IO流的读取写入

    在Java编程语言中,文件操作是一项基础且至关重要的任务,涉及到数据的持久化存储和传输。本主题将深入探讨如何使用Java实现文件复制、File类的文件读取和写入,以及I/O流的读取与写入。下面将详细阐述这些知识点。 ...

    数据流和多线程笔记

    通过对Java中的数据流和多线程的学习,我们可以更好地理解如何处理文件和其他形式的数据输入输出,以及如何利用多线程来提高程序的性能。掌握这些技术对于开发高效稳定的Java应用程序至关重要。

    一个文件读取写入方法类

    本篇文章将详细讲解一个用于文件读取和写入的方法类,以及如何根据文件路径将其转换为`byte[]`或`String`等不同格式。 首先,我们来理解文件读取的基本概念。文件读取是指从磁盘或其他存储介质中获取数据到内存的...

    Java基础整理

    - **线程安全**:多线程环境下资源的安全性问题。可以通过同步机制如`synchronized`关键字来保证线程安全。 - **死锁**:两个或多个线程互相等待对方持有的锁而无法继续执行的情况。 - **线程间通信**:线程之间通过...

    java关于文件的操作

    在多线程环境下进行文件操作时,需要注意线程安全问题。例如,使用`AtomicInteger`和`AtomicLong`来控制文件序列号的生成,确保在多线程环境下的原子性。 示例代码: ```java private static AtomicInteger ...

    JAVA SE概要点总结

    `String`类是不可变的,而`StringBuilder`和`StringBuffer`在多线程环境下提供可变字符串。`Math`类包含各种数学运算,`UUID`用于生成唯一标识,`Random`用于生成随机数。 **13. 多线程** Java通过`Thread`类支持多...

Global site tag (gtag.js) - Google Analytics