优化BufferedRandomAccessFile。
优化原则:
- 多重嵌套逻辑判断时,最可能出现的判断,应放在最外层。
这里举一典型的例子:
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的方式。
分享到:
相关推荐
在C/C++编程中,实现线程断点续传是一项技术...在Cocos2dx项目中,通过合理设计和利用其API,可以实现高效且稳定的断点续传下载功能。对于开发者来说,理解并掌握这些知识点对于提升应用性能和用户体验具有重要意义。
Java 断点续传技术是网络传输中常用的一种机制,特别是在大文件下载或上传时,如果因为网络中断或其他原因导致传输...通过合理的设计和实现,我们可以创建高效且可靠的断点续传功能,无论是在单线程还是多线程环境中。
在Android开发中,断点续传是一项...总之,Android的断点续传技术结合了随机流的文件操作能力和多线程的并发处理,使得大文件下载更加高效和可靠。通过理解这些技术并动手实践,开发者可以为用户提供更好的下载体验。
此外,将大文件分成多个小块进行断点续传,可以更高效地处理。 6. **存储状态信息**:客户端需要记录当前的下载进度,包括已下载的字节数和当前文件的总大小。这通常通过临时文件、配置文件或数据库来实现。 7. **...
综上所述,Java实现断点续传涉及了网络通信、文件操作、错误处理等多个方面,通过合理的架构设计和代码实现,可以创建一个高效、可靠的断点续传程序。在实际开发中,可以根据项目需求进行优化,例如考虑多线程下载以...
断点续传下载技术在Java中的实现是一种高效且灵活的文件下载策略,尤其适用于大文件的传输。这种技术允许用户在中断下载后从上次中断的地方继续,而不是从头开始,大大提高了用户体验。以下是对这个主题的详细解释:...
在实现时,可能需要使用`RandomAccessFile`或`FileChannel`来高效地读取文件的指定范围。 4. **缓存管理**: 断点续传通常涉及到客户端的本地缓存。为了支持续传,客户端需要保存已接收的文件部分,以便在下次请求...
- **RandomAccessFile**:客户端使用RandomAccessFile类,它可以随机访问文件的任意位置,这在断点续传中至关重要。客户端可以定位到已下载文件的末尾,然后从那里开始接收新的数据。 - **BufferedInputStream/...
Java多线程端点续传下载(MultiDown)是一种高效的文件下载技术,它结合了多线程和断点续传的概念,以优化网络资源利用,提高大文件下载速度和可靠性。在Java中实现这样的功能,我们需要理解以下几个核心知识点: 1...
### Java实现FTP多线程断点续传:深入解析与技术要点 在现代软件开发中,数据传输是一项基本且关键的任务,特别是在处理...通过理解并应用上述关键技术点,开发者可以在自己的项目中实现高效、稳定的FTP断点续传功能。
在断点续传过程中,`FileInputStream`和`FileOutputStream`可用于读写文件,而`RandomAccessFile`则能让我们在文件的任何位置进行读写操作。 为了实现多文件断点续传,我们需要一个管理器来跟踪每个文件的状态。这...
多线程断点续传是一种在大文件传输中常见的优化技术,它允许用户在中断传输后从上次停止的地方继续,而无需重新下载整个文件。...通过深入学习和实践,你将能够创建自己的高效、可靠的断点续传程序。
Java 实现下载断点续传是...以上是Java实现下载断点续传的核心技术和要点,通过这些技术,我们可以构建一个高效、稳定的文件下载系统,提高用户的下载体验。在实际开发中,还可以根据项目需求进行更深入的定制和优化。
然后,可以使用`java.io.RandomAccessFile`类来写入这个数据流,将接收到的字节保存到本地文件的相应位置,实现断点续传。 在使用`RandomAccessFile`时,可以通过`seek()`方法定位到文件的特定位置,然后使用`write...
Java 断点续传与多线程下载是网络编程...通过合理的文件分割、线程管理和数据合并,开发者可以构建出高效且可靠的下载系统。在实践中,结合适当的网络库和Java的并发机制,我们可以实现功能强大且灵活的下载解决方案。
本项目采用SpringBoot框架实现了一种高效、可靠的解决方案,支持大文件的分片上传和断点续传功能。以下是该技术实现的核心知识点: 1. **大文件上传**:大文件上传是指处理超过内存或服务器限制的文件,避免一次性...
通过对Xutils框架的深入理解和合理运用,我们可以构建出稳定、高效的多线程断点续传下载系统。 以上就是Xutils框架实现多线程断点续传的基本流程和关键知识点。通过学习和实践,开发者可以更好地利用Xutils这一工具...