您的位置:首页 > 移动开发

MappedByteBuffer基本使用与优点

2017-09-24 22:01 615 查看
有些文件太大,而不能全部放入内存操作,内存映射文件允许我们创建和修改那些因为太大而不能放入内存的文件。有了内存映射文件,

我们就可以假定整个文件都放在内存中,而且可以完全把它当做非常大的数组来访问。

MappedByteBuffer由ByteBuffer继承而来,因此它具有ByteBuffer的所有方法。使用MappedByteBuffer似乎我们可以一次访问到整个文件,

但是其实是只有一部分放入了内存,文件的其他部分被交换了出去。用这种方式,很大的文件(可达2G)也可以很容易的修改。

下面对“旧”的io和nio在映射文件访问上坐比较:

public class MappedIO {
private static int numOfInts = 4000000;
private static int numOfUbuffInts = 20000;

private abstract static class Tester {
private String name;

public Tester(String name) {
this.name = name;
}

public void runTest() {
System.out.println(name + ": ");
try {
long start = System.nanoTime();
test();
double duration = System.nanoTime() - start;
System.out.format("%.5f\n", duration / 1.0e9);
} catch (IOException e) {
e.printStackTrace();
}
}

public abstract void test() throws IOException;
}

private static Tester[] testers = {
new Tester("Stream Write") {
public void test() throws IOException {
DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(new File("temp.tmp"))));
for (int i = 0; i < numOfInts; i++)
dos.writeInt(i);
dos.close();
}
},
new Tester("Mapped Write") {
@Override
public void test() throws IOException {
FileChannel fc = new RandomAccessFile("temp.tmp", "rw").getChannel();
IntBuffer ib = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()).asIntBuffer();
for (int i = 0; i < numOfInts; i++)
ib.put(i);
fc.close();
}
},
new Tester("Stream Read") {
@Override
public void test() throws IOException {
DataInputStream dis = new DataInputStream(new BufferedInputStream(new FileInputStream("temp.tmp")));
for (int i = 0; i < numOfUbuffInts; i++)
dis.readInt();
dis.close();
}
},
new Tester("Mapped Read") {
@Override
public void test() throws IOException {

4000
FileChannel fc = new FileInputStream(new File("temp.tmp")).getChannel();
IntBuffer ib = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()).asIntBuffer();
while (ib.hasRemaining())
ib.get();
fc.close();
}
},
new Tester("Stream Read/Write") {
@Override
public void test() throws IOException {
RandomAccessFile raf = new RandomAccessFile(new File("temp.tmp"), "rw");
raf.writeInt(1);
for (int i = 0; i < numOfUbuffInts; i++) {
raf.seek(raf.length() - 4);
raf.writeInt(raf.readInt());
}
raf.close();
}
},
new Tester("Mapped Read/Write") {
@Override
public void test() throws IOException {
FileChannel fc = new RandomAccessFile(new File("temp.tmp"), "rw").getChannel();
IntBuffer ib = fc.map(FileChannel.MapMode.READ_WRITE, 0, fc.size()).asIntBuffer();
ib.put(0);
for (int i = 1; i < numOfUbuffInts; i++)
ib.put(ib.get(i - 1));
fc.close();
}
}

};

public static void main(String[] args) {
for (Tester test : testers) {
test.runTest();
}
}

}

效果:

Stream Write: 

0.27245

Mapped Write: 

0.01656

Stream Read: 

0.00279

Mapped Read: 

0.00789

Stream Read/Write: 

0.33709

Mapped Read/Write: 

0.00179

可以看到,整体收益比起Io流来说还是很显著的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  io nio java