`
zhang_xiujiao
  • 浏览: 11734 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类

高效的RandomAccessFile【续】

阅读更多

优化BufferedRandomAccessFile。

 

优化原则:

  •     调用频繁的语句最需要优化,且优化的效果最明显。
  •     多重嵌套逻辑判断时,最可能出现的判断,应放在最外层。
  •     减少不必要的NEW。


这里举一典型的例子:

 

   public void seek(long pos) throws IOException {
		...
         this.bufstartpos =  pos * bufbitlen / bufbitlen; // bufbitlen指buf[]的位长,例:若bufsize=1024,则bufbitlen=10。
                ...
  }
 

seek函数使用在各函数中,调用非常频繁,上面加重的这行语句根据pos和bufsize确定buf[]对应当前文件的映射位置,用"*"、"/"确定,显然不是一个好方法。

 

  • 优化一:this.bufstartpos = (pos << bufbitlen) >> bufbitlen;
  • 优化二:this.bufstartpos = pos & bufmask; // this.bufmask = ~((long)this.bufsize - 1);

两者效率都比原来好,但后者显然更好,因为前者需要两次移位运算、后者只需一次逻辑与运算(bufmask可以预先得出)。

至此优化基本实现,逐字节COPY一个12兆的文件,(这里牵涉到读和写,结合缓冲读,用优化后BufferedRandomAccessFile试一下读/写的速度):

 

耗用时间(秒)
RandomAccessFile RandomAccessFile 95.848
BufferedInputStream + DataInputStream BufferedOutputStream + DataOutputStream 2.935
BufferedRandomAccessFile BufferedOutputStream + DataOutputStream 2.813
BufferedRandomAccessFile BufferedRandomAccessFile 2.453
BufferedRandomAccessFile优 BufferedRandomAccessFile优 2.197

 

可见优化尽管不明显,还是比未优化前快了一些,也许这种效果在老式机上会更明显。

以上比较的是顺序存取,即使是随机存取,在绝大多数情况下也不止一个BYTE,所以缓冲机制依然有效。而一般的顺序存取类要实现随机存取就不怎么容易了。


需要完善的地方

 

提供文件追加功能:

 

public boolean append(byte bw) throws IOException {
   return this.write(bw, this.fileendpos + 1);
}

 

提供文件当前位置修改功能:

 

public boolean write(byte bw) throws IOException {
   return this.write(bw, this.curpos);
}

 

返回文件长度(由于BUF读写的原因,与原来的RandomAccessFile类有所不同):

 

public long length() throws IOException {
   return this.max(this.fileendpos + 1, this.initfilelen);
}

 

返回文件当前指针(由于是通过BUF读写的原因,与原来的RandomAccessFile类有所不同):

 

public long getFilePointer() throws IOException {
   return this.curpos;
}

 

提供对当前位置的多个字节的缓冲写功能:

 

public void write(byte b[], int off, int len) throws IOException {
        long writeendpos = this.curpos + len - 1;
        if (writeendpos <= this.bufendpos) { // b[] in cur buf
            System.arraycopy(b, off, this.buf, (int)(this.curpos - this.bufstartpos), len);
            this.bufdirty = true;
            this.bufusedsize = (int)(writeendpos - this.bufstartpos + 1);
        } else { // b[] not in cur buf
            super.seek(this.curpos);
            super.write(b, off, len);
        }
        if (writeendpos > this.fileendpos)
            this.fileendpos = writeendpos;
        this.seek(writeendpos+1);
}
public void write(byte b[]) throws IOException {
        this.write(b, 0, b.length);
}

 

提供对当前位置的多个字节的缓冲读功能:

 

public int read(byte b[], int off, int len) throws IOException {
    long readendpos = this.curpos + len - 1;
    if (readendpos <= this.bufendpos && readendpos <= this.fileendpos ) { // read in buf
     	System.arraycopy(this.buf, (int)(this.curpos - this.bufstartpos), b, off, len);
    } else { // read b[] size > buf[]
   	if (readendpos > this.fileendpos) { // read b[] part in file
      	len = (int)(this.length() - this.curpos + 1);
    }
       super.seek(this.curpos);
       len = super.read(b, off, len);
       readendpos = this.curpos + len - 1;
   }
       this.seek(readendpos + 1);
       return len;
}
public int read(byte b[]) throws IOException {
   return this.read(b, 0, b.length);
}
public void setLength(long newLength) throws IOException {
   if (newLength > 0) {
       this.fileendpos = newLength - 1;
   } else {
       this.fileendpos = 0;
   }
   super.setLength(newLength);
}
    
public void close() throws IOException {
   this.flushbuf();
   super.close();
}
 

至此完善工作基本完成,试一下新增的多字节读/写功能,通过同时读/写1024个字节,来COPY一个12兆的文件,(这里牵涉到读和写,用完善后BufferedRandomAccessFile试一下读/写的速度):

 

耗用时间(秒)
RandomAccessFile RandomAccessFile 95.848
BufferedInputStream + DataInputStream BufferedOutputStream + DataOutputStream 2.935
BufferedRandomAccessFile BufferedOutputStream + DataOutputStream 2.813
BufferedRandomAccessFile BufferedRandomAccessFile 2.453
BufferedRandomAccessFile优 BufferedRandomAccessFile优 2.197
BufferedRandomAccessFile完 BufferedRandomAccessFile完 0.401


与MappedByteBuffer+RandomAccessFile的对比?

 

JDK1.4+提供了NIO类 ,其中MappedByteBuffer类用于映射缓冲,也可以映射随机文件访问,可见JAVA设计者也看到了RandomAccessFile的问题, 并加以改进。怎么通过MappedByteBuffer+RandomAccessFile拷贝文件呢?下面就是测试程序的主要部分:

 

RandomAccessFile rafi = new RandomAccessFile(SrcFile, "r");
RandomAccessFile rafo = new RandomAccessFile(DesFile, "rw");
FileChannel fci = rafi.getChannel();
FileChannel fco = rafo.getChannel();
long size = fci.size();
MappedByteBuffer mbbi = fci.map(FileChannel.MapMode.READ_ONLY, 0, size);
MappedByteBuffer mbbo = fco.map(FileChannel.MapMode.READ_WRITE, 0, size);
long start = System.currentTimeMillis();
for (int i = 0; i < size; i++) {
    byte b = mbbi.get(i);
    mbbo.put(i, b);
}
fcin.close();
fcout.close();
rafi.close();
rafo.close();
System.out.println("Spend: "+(double)(System.currentTimeMillis()-start) / 1000 + "s");
 

试一下JDK1.4的映射缓冲读/写功能,逐字节COPY一个12兆的文件,(这里牵涉到读和写):

 

耗用时间(秒)
RandomAccessFile RandomAccessFile 95.848
BufferedInputStream + DataInputStream BufferedOutputStream + DataOutputStream 2.935
BufferedRandomAccessFile BufferedOutputStream + DataOutputStream 2.813
BufferedRandomAccessFile BufferedRandomAccessFile 2.453
BufferedRandomAccessFile优 BufferedRandomAccessFile优 2.197
BufferedRandomAccessFile完 BufferedRandomAccessFile完 0.401
MappedByteBuffer+ RandomAccessFile MappedByteBuffer+ RandomAccessFile 1.209

 

确实不错,看来NIO有了极大的进步。建议采用 MappedByteBuffer+RandomAccessFile的方式。

分享到:
评论
3 楼 fywxin 2012-10-26  
2 楼 415421979 2012-09-25  
好 不错 很有所获
1 楼 qxinghui 2012-07-20  
 

相关推荐

    c/c++线程断点续传实现

    在C/C++编程中,实现线程断点续传是一项技术...在Cocos2dx项目中,通过合理设计和利用其API,可以实现高效且稳定的断点续传下载功能。对于开发者来说,理解并掌握这些知识点对于提升应用性能和用户体验具有重要意义。

    java断点续传,刚刚整理出来多线程处理

    Java 断点续传技术是网络传输中常用的一种机制,特别是在大文件下载或上传时,如果因为网络中断或其他原因导致传输...通过合理的设计和实现,我们可以创建高效且可靠的断点续传功能,无论是在单线程还是多线程环境中。

    断点续传源代码

    在Android开发中,断点续传是一项...总之,Android的断点续传技术结合了随机流的文件操作能力和多线程的并发处理,使得大文件下载更加高效和可靠。通过理解这些技术并动手实践,开发者可以为用户提供更好的下载体验。

    java 段点续传 例子

    此外,将大文件分成多个小块进行断点续传,可以更高效地处理。 6. **存储状态信息**:客户端需要记录当前的下载进度,包括已下载的字节数和当前文件的总大小。这通常通过临时文件、配置文件或数据库来实现。 7. **...

    Java实现断点续传程序

    综上所述,Java实现断点续传涉及了网络通信、文件操作、错误处理等多个方面,通过合理的架构设计和代码实现,可以创建一个高效、可靠的断点续传程序。在实际开发中,可以根据项目需求进行优化,例如考虑多线程下载以...

    断点续传下载 (JAVA版 迅雷)

    断点续传下载技术在Java中的实现是一种高效且灵活的文件下载策略,尤其适用于大文件的传输。这种技术允许用户在中断下载后从上次中断的地方继续,而不是从头开始,大大提高了用户体验。以下是对这个主题的详细解释:...

    Spring MVC大文件的断点续传(File Transfer Resume)

    在实现时,可能需要使用`RandomAccessFile`或`FileChannel`来高效地读取文件的指定范围。 4. **缓存管理**: 断点续传通常涉及到客户端的本地缓存。为了支持续传,客户端需要保存已接收的文件部分,以便在下次请求...

    断点续传经典实例

    - **RandomAccessFile**:客户端使用RandomAccessFile类,它可以随机访问文件的任意位置,这在断点续传中至关重要。客户端可以定位到已下载文件的末尾,然后从那里开始接收新的数据。 - **BufferedInputStream/...

    JAVA多线程端点续传下载MultiDown.

    Java多线程端点续传下载(MultiDown)是一种高效的文件下载技术,它结合了多线程和断点续传的概念,以优化网络资源利用,提高大文件下载速度和可靠性。在Java中实现这样的功能,我们需要理解以下几个核心知识点: 1...

    java实现FTP多线程断点续传

    ### Java实现FTP多线程断点续传:深入解析与技术要点 在现代软件开发中,数据传输是一项基本且关键的任务,特别是在处理...通过理解并应用上述关键技术点,开发者可以在自己的项目中实现高效、稳定的FTP断点续传功能。

    Android多文件断点续传

    在断点续传过程中,`FileInputStream`和`FileOutputStream`可用于读写文件,而`RandomAccessFile`则能让我们在文件的任何位置进行读写操作。 为了实现多文件断点续传,我们需要一个管理器来跟踪每个文件的状态。这...

    多线程断点续传实践学习资料

    多线程断点续传是一种在大文件传输中常见的优化技术,它允许用户在中断传输后从上次停止的地方继续,而无需重新下载整个文件。...通过深入学习和实践,你将能够创建自己的高效、可靠的断点续传程序。

    java实现下载断点续传

    Java 实现下载断点续传是...以上是Java实现下载断点续传的核心技术和要点,通过这些技术,我们可以构建一个高效、稳定的文件下载系统,提高用户的下载体验。在实际开发中,还可以根据项目需求进行更深入的定制和优化。

    断点续传的文章,作者钟华,来自于IBM论坛

    然后,可以使用`java.io.RandomAccessFile`类来写入这个数据流,将接收到的字节保存到本地文件的相应位置,实现断点续传。 在使用`RandomAccessFile`时,可以通过`seek()`方法定位到文件的特定位置,然后使用`write...

    java断点续传与多线程下载

    Java 断点续传与多线程下载是网络编程...通过合理的文件分割、线程管理和数据合并,开发者可以构建出高效且可靠的下载系统。在实践中,结合适当的网络库和Java的并发机制,我们可以实现功能强大且灵活的下载解决方案。

    java实现大文件上传分片上传断点续传.zip

    本项目采用SpringBoot框架实现了一种高效、可靠的解决方案,支持大文件的分片上传和断点续传功能。以下是该技术实现的核心知识点: 1. **大文件上传**:大文件上传是指处理超过内存或服务器限制的文件,避免一次性...

    Xutils框架进行多线程断点续传(详细注解)

    通过对Xutils框架的深入理解和合理运用,我们可以构建出稳定、高效的多线程断点续传下载系统。 以上就是Xutils框架实现多线程断点续传的基本流程和关键知识点。通过学习和实践,开发者可以更好地利用Xutils这一工具...

Global site tag (gtag.js) - Google Analytics