说到高速缓存存储,处理读写文件,那就不得不说MappedByteBuffer。

看了好多文章以后写一下自己的总结。

在这里先介绍一下相关的类与方法。

先说一下Buffer、ByteBuffer、MappedByteBuffer这几个类之间的关系。

public abstract class Buffer {

    // Invariants: mark <= position <= limit <= capacity
private int mark = -;
private int position = ;
private int limit;
private int capacity;
long address;
......
} public abstract class ByteBuffer extends Buffer implements Comparable { // These fields are declared here rather than in Heap-X-Buffer in order to
// reduce the number of virtual method invocations needed to access these
// values, which is especially costly when coding small buffers.
//
final byte[] hb; // Non-null only for heap buffers
final int offset;
boolean isReadOnly; // Valid only for heap buffers
boolean bigEndian;
boolean nativeByteOrder;
......
}
//字节数组final byte[] hb就是所指的那块内存缓冲区 public abstract class MappedByteBuffer extends ByteBuffer{
private final FileDescriptor fd;
......
}

public abstract class MappedByteBuffer extends ByteBuffer 直接字节缓冲区,其内容是文件的内存映射区域。

映射的字节缓冲区是通过 FileChannel.map 方法创建的。此类用特定于内存映射文件区域的操作扩展 ByteBuffer 类。 
映射的字节缓冲区和它所表示的文件映射关系在该缓冲区本身成为垃圾回收缓冲区之前一直保持有效。 
映射的字节缓冲区的内容可以随时更改,例如,在此程序或另一个程序更改了对应的映射文件区域的内容的情况下。这些更改是否发生(以及何时发生)与操作系统无关,因此是未指定的。 
全部或部分映射的字节缓冲区可能随时成为不可访问的,例如,如果我们截取映射的文件。试图访问映射的字节缓冲区的不可访问区域将不会更改缓冲区的内容,并导致在访问时或访问后的某个时刻抛出未指定的异常。因此强烈推荐采取适当的预防措施,以避免此程序或另一个同时运行的程序对映射的文件执行操作(读写文件内容除外)。

除此之外,映射的字节缓冲区的功能与普通的直接字节缓冲区完全相同。

public RandomAccessFile(File file, String mode)throws FileNotFoundException
创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定。将创建一个新的 FileDescriptor 对象来表示此文件的连接。 
r" 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。 
"rw" 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。 
"rws" 打开以便读取和写入,对于 "rw",还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。 
"rwd" 打开以便读取和写入,对于 "rw",还要求对文件内容的每个更新都同步写入到底层存储设备。

public final FileChannel getChannel()返回与此文件关联的唯一 FileChannel 对象。 
返回通道的 java.nio.channels.FileChannel#position()position 将始终等于 getFilePointer 方法返回的此对象的文件指针偏移量。显式或者通过读取或写入字节来更改此对象的文件指针偏移量将更改通道的位置,反之亦然。通过此对象更改此文件的长度将更改通过文件通道看到的长度,反之亦然。

public abstract MappedByteBuffer map(FileChannel.MapMode mode,long position,long size)throws IOException将此通道的文件区域直接映射到内存中。 
mode - 根据是按只读、读取/写入或专用(写入时拷贝)来映射文件,分别为 FileChannel.MapMode类中所定义的 READ_ONLY、READ_WRITE 或 PRIVATE 之一
position - 文件中的位置,映射区域从此位置开始;必须为非负数
size - 要映射的区域大小;必须为非负数且不大于 Integer.MAX_VALUE

下面一个运行的例子:

package com.tzx.ne;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel; public class MappedByteBufferDemo {
public static void main(String[] args) throws Exception{
/**
* output: 0.001s(读)
* input: 0.11s(写)
* */
MappedByteBufferTest();
/**
* size=1024*8
* out: 0.0s
* input: 0.014s
* */
/**
* size=1024*1024*8
* output: 0.01s
* input: 0.014s
* */
/**
* size=80
* output: 0.0s
* input: 0.546s
* */
//BufferTest();
/**
* time: 0.585s
* */
//BufferedInputStreamTest();
} /*
* 测试结果与Buffer size有关
*/
// 1、使用MappedByteBuffer: 0.7s
public static void MappedByteBufferTest() throws Exception{
String srcFile = "F:\\Ebook\\偷天.txt";
String destFile = "F:\\Ebook\\toutian.txt";
RandomAccessFile rafi = new RandomAccessFile(srcFile, "r");
RandomAccessFile rafo = new RandomAccessFile(destFile, "rw");
FileChannel fci = rafi.getChannel();
FileChannel fco = rafo.getChannel();
long size = fci.size();
byte b;
long start = System.currentTimeMillis();
MappedByteBuffer mbbi = fci.map(FileChannel.MapMode.READ_ONLY, , size);
System.out.println("output: " + (double) (System.currentTimeMillis() - start) / + "s");
MappedByteBuffer mbbo = fco.map(FileChannel.MapMode.READ_WRITE, , size);
start = System.currentTimeMillis();
for (int i = ; i < size; i++) {
b = mbbi.get(i);
mbbo.put(i, b);
}
fci.close();
fco.close();
rafi.close();
rafo.close();
System.out.println("input: " + (double) (System.currentTimeMillis() - start) / + "s");
} // 2、自己处理Buffer(RandomAccessFile): 0.13s
public static void BufferTest() throws Exception{
String srcFile = "F:\\Ebook\\偷天.txt";
String destFile = "F:\\Ebook\\toutian.txt";
RandomAccessFile rafi = new RandomAccessFile(srcFile, "r");
RandomAccessFile rafo = new RandomAccessFile(destFile, "rw"); byte[] buf = new byte[];
long start = System.currentTimeMillis();
int c = rafi.read(buf);
System.out.println("output: " + (double) (System.currentTimeMillis() - start) / + "s");
start = System.currentTimeMillis();
while (c > ) {
if (c == buf.length) {
rafo.write(buf);
} else {
rafo.write(buf, , c);
} c = rafi.read(buf);
}
System.out.println("input: " + (double) (System.currentTimeMillis() - start) / + "s");
rafi.close();
rafo.close(); } // 3、BufferedInputStream&BufferedOutputStream: 3.02s
public static void BufferedInputStreamTest() throws Exception{
String srcFile = "F:\\Ebook\\偷天.txt";
String destFile = "F:\\Ebook\\toutian.txt";
FileInputStream rafi = new FileInputStream(srcFile);
FileOutputStream rafo = new FileOutputStream(destFile); BufferedInputStream bis = new BufferedInputStream(rafi, );
BufferedOutputStream bos = new BufferedOutputStream(rafo, );
long size = rafi.available(); long start = System.currentTimeMillis(); for (int i = ; i < size; i++) {
byte b = (byte) bis.read();
bos.write(b);
}
rafi.close();
rafo.close();
System.out.println("time: " + (double) (System.currentTimeMillis() - start) / + "s"); }
}

总结:

1、RandomAccessFile是Java输入输出流体系中功能最丰富的文件内容访问类,他提供 了众多的方法来访问文件,它既可以读取文件的内容,也可以说向文件输出数据,本身不带缓冲读写,和FileInputStream、FileOutputStream等一样,直接按字节读写时,性能不可接受;

2、使用MappedByteBuffer读写,固然性能会得到极大提升;其实只要自己处理缓冲,性能都会有非常大的提升,比如以下两种方式中第一种使用了MappedByteBuffer,第二种自己进行缓冲处理后,对于几兆的文件,后者的效率甚至高于前者,可以从几个size大小看出运行速度,当size较大的时候一次性的读取速度是慢些,但是整体的效率非常之高。

3、BufferedXXXX之类的缓冲流,如果仅使用默认的buffer size,性能不一定最优,要权衡不同情况各种因素设置大小。

MappedByteBuffer高速缓存文件、RandomAccessFile随机访问的更多相关文章

  1. [19/04/03-星期三] IO技术_其它流(RandomAccessFile 随机访问流,SequenceInputStream 合并流)

    一.RandomAccessFile 随机访问流 [版本1] /* *RandomAccessFile 所谓随机读取就是 指定位置开始或指定位置结束 的读取写入文件 * 实现文件的拆分与合并 模拟下载 ...

  2. Java I/O(三)各种Reader和Writer读写器、RandomAccessFile随机访问文件、序列化

    2019 01/01 八.Reader和Writer读写器 前面讲的输入输出流的基本单位都是字节,因此可以称为“字节流”,读写器是以字符为基本单位,可以称为“字符流”.它们的使用方法非常相似,因此我考 ...

  3. 18 IO流(十五)——RandomAccessFile随机访问文件及使用它进行大文件切割的方法

    本文部分内容转自:https://blog.csdn.net/nightcurtis/article/details/51384126 1.RandomAccessFile特点 RandomAcces ...

  4. JavaIO之RandomAccessFile随机访问文件

    package test.java.io; import java.io.RandomAccessFile; public class RandomAccFile { public static vo ...

  5. 系统学习 Java IO (四)----文件的读写和随机访问 FileInputStream/FileOutputStream & RandomAccessFile

    目录:系统学习 Java IO---- 目录,概览 文件输入流 FileInputStream 这是一个简单的FileInputStream示例: InputStream input = new Fi ...

  6. Java基础知识强化之IO流笔记63:随机访问流RandomAccessFile

    1. 随机访问流RandomAccessFile RandomAccessFile类不属于流,是Object类的子类.但它融合了InputStream和OutputStream的功能.支持对随机访问文 ...

  7. Java基础-IO流对象之随机访问文件(RandomAccessFile)

    Java基础-IO流对象之随机访问文件(RandomAccessFile) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.RandomAccessFile简介 此类的实例支持对 ...

  8. java 21 - 12 随机访问流(不属于IO流)

    随机访问流: RandomAccessFile类不属于流,是Object类的子类. 但它融合了InputStream和OutputStream的功能. 支持对文件的随机访问读取和写入. public ...

  9. Java:IO流其他类(字节数组流、字符数组流、数据流、打印流、Properities、对象流、管道流、随机访问、序列流、字符串读写流)

    一.字节数组流: 类 ByteArrayInputStream:在构造函数的时候,需要接受数据源,而且数据源是一个字节数组. 包含一个内部缓冲区,该缓冲区包含从流中读取的字节.内部计数器跟踪 read ...

随机推荐

  1. Android WebView Error – Uncaught TypeError: Cannot call method ‘getItem’ of null at

    本质原因是js 没有判断dom 是否加载完毕 其实就是在dom 加载完毕之后处理事件 wv.getSettings().setDomStorageEnabled(true); 转自 蛙齋  http: ...

  2. VS2012 无法启动IIS Express Web服务器的解决方案

    本文转载:http://blog.csdn.net/hongleidy5000/article/details/22732621 打开VS2012解决方案资源管理器 -> 点选 Web 项目选择 ...

  3. .NET 性能分析工具

    Download .NET Profiler http://www.yourkit.com/dotnet/download/ dotTrace 5.5 Performance http://www.j ...

  4. Solaris下怎样改动文件创建时间及查询

    Solaris下怎样改动文件创建时间及查询 实验演示: 1.核对时间 [root@S1011:/]# date Tue Jul 15 21:37:01 CDT 2014 --若时间不对请先按例如以下格 ...

  5. pat 1062. Talent and Virtue (25)

    难得的一次ac 题目意思直接,方法就是对virtue talent得分进行判断其归属类型,用0 1 2 3 4 表示 不合格 sage noblemen foolmen foolmen 再对序列进行排 ...

  6. [资源分享]神州数码 思科 UCS 虚拟化培训资料

    神州数码 思科 UCS 虚拟化培训资料   点击文件名下载 UCS统一计算平台=.pdf 云计算Demo实验教材_Nexus 5K2K实验.pdf 云计算数据中心架构与技术.pdf 云计算数据中心虚拟 ...

  7. [PWA] 11. Serve skeleton cache for root

    Intead of cache the root floder, we want to cache skeleton instead. self.addEventListener('install', ...

  8. iOS UI布局调试工具

    查看ios软件的ui布局有三种: 1.DCIntrospect    这种方式是开源的,我从github上clone下来后运行demo,运行遇到了问题:Xcode cannot run using t ...

  9. Android(java)学习笔记214:开源框架的文件上传(只能使用Post)

    1.文件上传给服务器,服务器端必然要写代码进行支持,如下: 我们新建一个FileUpload.jsp的动态网页,同时我们上传文件只能使用post方式(不可能将上传数据拼凑在url路径下),上传数据Ap ...

  10. 进程外session(session保存在sqlserver)

    .Session保存在SQLServer中配置方法 )运行.NetFramework安装目录下对应版本的aspnet_regsql.exe 来创建相关的数据库.表和存储过程等,比如: C:\Windo ...