笔记:i/o流-内存映射文件

追寻自由的路途 追寻自由的路途     2022-08-30     128

关键词:

内存映射文件时利用虚拟内存实现来将一个文件或者文件的一部分映射到内存中,然后整个文件就可以当作数组一样的访问,这个比传统的文件操作要快得多,Java 使用内存映射文件首先需要从文件中获取一个channel(通道),通道时磁盘文件的一个抽象,他使得我们可以访问诸如内存映射、文件加锁机制以及文件间快速数据传递等操作系统特性,然后通过调用 FileChannel 类的 map 方法从这个通道获取一个映射块(ByteBuffer),然后就可以读取/写入文件块内容,map 支持的模式有如下:

  • FileChannel.MapMode.READ_ONLY:所产生的缓冲区是只读的,如果对只读的缓冲区进行写操作,将会导致 ReadonlyBufferException 异常
  • FileChannel.MapMode.READ_WRITE:所产生的缓冲区是可写的,任何修改都会在某个时刻写回文件(写入不是及时的)
  • FileChannel.MapMode.PRIVATE:所产生的缓冲区是可写的,但是任何修改对这个缓冲区来说都是私有的,不会传播到文件中

映射文件示例代码:

  • 读取文件:

    ?????????Path filePath = Paths.get("D:\我的游戏\World of Warcraft\Data\data", "data.001");

    ?????????long startTime = System.currentTimeMillis(); //获取开始时间

    ????????try {

    ???????????????try (FileChannel channel = FileChannel.open(filePath, StandardOpenOption.READ)) {

    ???????????????????????int size = 40960;

    ???????????????????????long readByteSize = 0;

    ???????????????????????ByteBuffer byteBuffer = ByteBuffer.allocate(size);

    ???????????????????????int readCount;

    ????????????????????????do {

    ?????????????????????????????????readCount = channel.read(byteBuffer);

    ?????????????????????????????????byte[] readBytes = new byte[byteBuffer.limit()];

    ??????????????????????????????? // channel.read 后其 position 是 readCount,因此需要读取数据时,需要重置 position = 0

    ???????????????????????????????? byteBuffer.position(0);

    ?????????????????????????????????for(int i=0;i< readBytes.length;i++){

    ????????????????????????????????????????readBytes[i] = byteBuffer.get();

    ?????????????????????????????????}

    ?????????????????????????????????byteBuffer.clear();

    ??????????????????????????????? if (readCount != -1) {

    ???????????????????????????????????????readByteSize += readCount;

    ??????????????????????????????? ?}

    ??????????????????????????????? System.out.print("readCount +" + readCount + " readByteSize " + readByteSize + " ");

    ?????????????????????????} while (readCount != -1);

    ????????????????}

    ????????} catch (IOException ex) {

    ????????????????????????ex.printStackTrace();

    ?????? ?}

    ????????long endTime = System.currentTimeMillis(); //获取结束时间

    ????????System.out.println("程序运行时间: " + (endTime - startTime) + "ms");

    ? ?

  • 写入文件(使用 RandomAccessFile MappedByteBuffer):

    ????????????????Random random = new Random();

    ????????????????Path writeFilePath = Paths.get("d:\channel.dat");

    ????????????????startTime = System.currentTimeMillis(); //获取开始时间

    ????????????????try {

    ????????????????????????byte[] buff = new byte[40960];

    ????????????????????????long position = 0;

    ????????????????????????long size = buff.length;

    ????????????????????????RandomAccessFile randomAccessFile = new RandomAccessFile(writeFilePath.toString(), "rw");

    ????????????????????????try (FileChannel outChannel = randomAccessFile.getChannel()) {

    ????????????????????????????????for (int i = 0; i < 1000; i++) {

    ????????????????????????????????????????random.nextBytes(buff);

    ????????????????????????????????????????MappedByteBuffer buffer = outChannel.map(FileChannel.MapMode.READ_WRITE, position, size);

    ????????????????????????????????????????buffer.put(buff);

    ????????????????????????????????????????position += size;

    ????????????????????????????????}

    ????????????????????????}

    ????????????????} catch (IOException ex) {

    ????????????????????????ex.printStackTrace();

    ????????????????}

    ????????????????endTime = System.currentTimeMillis(); //获取结束时间

    ????????????????System.out.println("程序运行时间: " + (endTime - startTime) + "ms");

    ? ?

笔记:i/o流-字符集

Java 库的 java.nio 包用 Charset 类统一了对字符集的转换,支付姐建立了两个字节Unicode码元序列与使用本地字符编码方式的字节序列之间的映射,Charset类使用的时由IANA字符集注册中心标准化的字符集名称,为了兼容其他的... 查看详情

带有流的文件 I/O - 最佳内存缓冲区大小

】带有流的文件I/O-最佳内存缓冲区大小【英文标题】:FileI/Owithstreams-bestmemorybuffersize【发布时间】:2011-03-0307:17:20【问题描述】:我正在编写一个小型I/O库来协助一个更大的(爱好)项目。该库的一部分对文件执行各种功能,... 查看详情

i/o基础之概念

1:I/O流就是常说的输入/输出流,用于数据在内存与存储设备(硬盘,文件等)之间的数据传输。2 :分类     根据操作分:输入流与输出流  输入流:将外部设备中的数据(包括网络数据)读入内存  输... 查看详情

存储映射i/o

...地址空间是4G。不过,内核在管理进程的地址空间时是以内存区域为单位。内存区域是进程整个地址空间中一个独立的内存范围,它在内核中使用vm_area_struct数据结构来描述。每个内存区域都有自己访问权限以及操作函数,因此... 查看详情

cpu的端口映射i/o和内存映射i/o

   CPU在访问内存时,通过数据总线和地址总线和内存交换信息,进行读写操作,这是内存映射I/O。     而当CPU访问外接设备时,可通过内存映射和端口映射两种方式进行I/O操作,通过内存映射访问设... 查看详情

文件i/o操作

...来说,每两个字节代表一个字符)。如整形数12345,其在内存 查看详情

输入输出流(i/o)

...件存取有关,但是程序的源和目的地也可以是键盘鼠标、内存或显示器窗口等。Java由数据流处理输入输出模式,程序从指向源的输入流中读取源中的数据。源可以是文件、网络、压缩包或者其他数据源。输出流的指向是数据要 查看详情

标准i/o库笔记

标准I/O库1.流和FILE对象a) ASCII字符集:一个字符用一个字节表示b) 国际字符:一个字符可以用多个字节表示c) 标准I/O文件流可以用于单字节或者多字节字符集2.流定向a) 决定所读、写的字符是单字节或者是多字节b) 流... 查看详情

浅谈内存映射i/o(mmio)与端口映射i/o(pmio)的区别

最近在看NVMeDirect和SPDK的源码,觉得有必要梳理一下MMIO和PMIO的区别。关于MMIO和PMIO,维基百科上是这么讲滴,Memory-mappedI/O(MMIO)andport-mappedI/O(PMIO)(whichisalsocalledisolatedI/O)aretwocomplementarymethodsofperforminginput/output(I/O)be 查看详情

javai/o

.../O接口:Socket 三、磁盘I/O工作机制  1、读写文件:内存缓存机制: 查看详情

笔记:i/o流-对象序列化

Java 语言支持一种称为对象序列化(Object Serialization)的非常通用的机制,可以将任何对象写入到流中,并在之后将其读回,首先需要支持对象序列化的类,必须继承与 Serializable 接口,该接口没有任何方法,只是对类起... 查看详情

内存映射文件

 一段内存地址空间,映射着物理存储器上一个已经存在于磁盘上的文件。在对该文件进行操作之前必须首先对文件进行映射。使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作。内存映射文件,是由... 查看详情

java学习之路--i/o流

...的,java有一个类叫File,它封装的是文件的文件名,只是内存里面的一个对象,真正的文件是在硬盘上的一块空间,在这个文件里面存放着各种各样的数据,我们想读文件里面的数据怎么办呢?是通过一个流的方式来读,咱们要... 查看详情

i/o流

...:输入流和输出流。输入流:把数据从其他设备上读取到内存中的流。输出流:把数据从内存中写出到其他设备上的流。根据数据的类型分为:字节流和字符流。字节流:以字节为单位,读写数据的流。字符流:以字符为单位,... 查看详情

java学习笔记6.1.1字节流-数据字节输入流与数据字节输出流

文章目录零、本讲学习目标一、I/O流(一)I/O流定义(二)I/O流分类(三)I/O流层次结构(四)数据的输出(五)数据的输入(六)声明I/O流四个顶级抽象类二、字节流(一)字节流定义(二)字节流示意图(三)字节输入流1... 查看详情

i/o(输入/输出)---字节流与字符流

流:  分为输入流和输出流,输入/输出是相对计算机内存来说的,数据输入到内存是输入流,数据从内存中输出是输出流。  流对象构造的时候会和数据源联系起来。  数据源分为:源数据源和目标数据源。输入流联系... 查看详情

文件i/o

文件I/O 操作主要有以下几种:1.文件输入流ifstream2.文件输出流ofstream3.文件输入输出流fstream4.文件的打开方式5.文件流的状态6.文件流的定位:文件指针(输入指针、输出指针)7.文本文件和二进制文件 文件流类和文件流... 查看详情

i/o流

booleanexists():判断这个文件是否存在 booleanmkdir():创建文件夹路径(只能建一层)--makeDirectory booleanmkdirs():创建文件夹路径 createNewFile():创建文件 delete():删除文件 renameTo(Filefile):对文件进行更名操作 getName:获取文件名称 getPath... 查看详情