0
点赞
收藏
分享

微信扫一扫

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构


 

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据

 


笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_java_02

 1.7 NIO

JDK 1.4 开始,引入了 java.nio 包

主要功能:

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_03

 字符集编码解码

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_04

 非阻塞IO

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_05

 内存映射文件

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_06

 文件加锁机制

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_蓝桥杯_07

 1.7.1 内存映射文件

将虚拟内存映射,从而实现文件的方法和操作,这样处理,要比传统IO要快。可以看做传统IO是拷贝完副本后进行一系列操作,再照着修改原数据;内存映射是直接改原数据,省略了拷贝过程。

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_08

 获取通道

FileInputStream fio = new FileInputStream("");

FileChannel channel = in.getChannel();

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_09

 获取映射

MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY,0,length);

这里的模式有:

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_10

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_内存映射_11

 顺序遍历

while(buffer.hasRetaining()){

    byte b = buffer.get();

}

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_蓝桥杯_12

 随机访问

Byte b = buffer.get(i);

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_java_13

 判断文件损坏,计算校验和(不算文件会损坏)

for(int p = 0; p < length; p++){

      int c = buffer.get(p);

      crc.update(c);

}

return crc.getValue();

作者示例,比较不同方式读取数据计算校验和的效率:

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

import java.io.*;
import java.nio.*;
import java.nio.channels.FileChannel;
import java.util.zip.CRC32;

public class NIOTest {
public static long checksumInputStream(String filename) throws IOException {
InputStream in = new FileInputStream(filename);
CRC32 crc = new CRC32();

int c;
while((c=in.read())!=-1){
crc.update(c);
}
return crc.getValue();
}

public static long checksumBufferedInputStream(String filename) throws IOException{
InputStream in = new BufferedInputStream(new FileInputStream(filename));
CRC32 crc = new CRC32();
int c;
while((c=in.read())!=-1){
crc.update(c);
}
return crc.getValue();
}

public static long checksumRandomAccessFile(String filename) throws IOException{
RandomAccessFile file = new RandomAccessFile(filename,"r");
long length = file.length();
CRC32 crc = new CRC32();
for(long p = 0; p < length; p++){
file.seek(p);
int c = file.readByte();
crc.update(c);
}
return crc.getValue();
}

public static long checksumMappedFile(String filename) throws IOException{
FileInputStream in = new FileInputStream(filename);
FileChannel channel = in.getChannel();

CRC32 crc = new CRC32();
int length = (int) channel.size();
MappedByteBuffer buffer = channel.map(FileChannel.MapMode.READ_ONLY, 0, length);

for(int p = 0; p < length; p++){
int c = buffer.get(p);
crc.update(c);
}
return crc.getValue();
}

public static void main(String[] args) throws IOException {
String[] strs = new String[]{
"Input Stream:","Buffered Input Stream:","Random Access File:","Mapped File"
};


for(int i = 0; i < 4; i++){
System.out.println(strs[i]);
long start = System.currentTimeMillis();
long crcValue = getValue(i,"ext/A.txt");
long end = System.currentTimeMillis();
System.out.println(Long.toHexString(crcValue));
System.out.println((end-start)+ " milliseconds");
System.out.println();
}

}

private static long getValue(int index,String name) throws IOException {
switch (index){
case 0: return checksumInputStream(name);
case 1: return checksumBufferedInputStream(name);
case 2: return checksumRandomAccessFile(name);
case 3: return checksumMappedFile(name);

}
return 0L;
}
}

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

运行结果:

🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_内存映射_14

🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍

我测的结果是缓冲会快一点,可能和电脑设备之类有关,作者测试结果是内存映射快一点

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_内存映射_15

 1.7.2 缓冲区数据结构

进行内存映射时,可以使用缓冲区一次性读取合适的长度。

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_内存映射_16

 缓冲区数据结构(无StringBuffer!):

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_蓝桥杯_17

 ByteBuffer

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_java_18

 CharBuffer

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_内存映射_19

 DoubleBuffer

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_蓝桥杯_20

 IntBuffer

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_21

 LongBuffer

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_内存映射_22

 ShortBuffer

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_数据_23

 缓冲区特性:

容量:代表缓冲区能一次性装载数据的大小,它是固定不变的

读写位置:代表下一个读入点

界限:代表有效数据的边界,超过界限读取没有实际意义

标记:对一读写范围,可以打标记,用于重复读写

Buffer 相关方法【一般不贴,这个有点复杂】:

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_内存映射_24

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

import java.io.*;
import java.nio.CharBuffer;
import java.util.ArrayList;
import java.util.List;

public class Main {
public static void main(String[] args) throws IOException{
//写
String inputStr = "Love code, love java, love everything you did.";

List<CharBuffer> list = new ArrayList<>();

int n = inputStr.length();
CharBuffer buffer = CharBuffer.allocate(8);//容量
for(int i = 0; i < n; i++){
buffer.append(inputStr.charAt(i));
if(buffer.remaining()==0 || i == n-1){
list.add(buffer);
buffer = CharBuffer.allocate(8);
}
}

//读
StringBuilder sb = new StringBuilder();
int m = list.size();
for(CharBuffer b:list){
b.flip();//准备读,注意用flip设置界限,rewind的话,后面无法用remaining()判断
while (b.remaining()>0)
sb.append(b.get());
}
System.out.println(sb.toString());
}
}

❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤❤🧡💛💚💙💜🤎🖤

运行结果:

🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍

笔记 第1章 流与文件(11) NIO 内存映射与缓冲区结构_内存映射_25

🚗🚓🚕🛺🚙🚌🚐🚎🚑🚒🚚🚛🚜🚘🚔🚖🚍🦽🦼🛹🚲🛴🛵🏍


举报

相关推荐

0 条评论