栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

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

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

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

 

 

 1.7 NIO

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

主要功能:

 字符集编码解码

 非阻塞IO

 内存映射文件

 文件加锁机制

 1.7.1 内存映射文件

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

 获取通道

FileInputStream fio = new FileInputStream("");

FileChannel channel = in.getChannel();

 获取映射

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

这里的模式有:

 顺序遍历

while(buffer.hasRetaining()){

    byte b = buffer.get();

}

 随机访问

Byte b = buffer.get(i);

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

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.7.2 缓冲区数据结构

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

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

 ByteBuffer

 CharBuffer

 DoubleBuffer

 IntBuffer

 LongBuffer

 ShortBuffer

 缓冲区特性:

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

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

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

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

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

❤李癩❤李癩❤李癩

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 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());
    }
}

❤李癩❤李癩❤李癩

运行结果:

尿寮

尿寮

 评论点赞收藏✨关注,是送给作者最好的礼物,愿我们共同学习,一起进步

如果对作者发布的内容感兴趣,可点击下方关注公众号 钰娘娘知识汇总 查看更多作者文章哦!

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/932613.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号