关于JAVA中顺序IO的基本操作


写在前面

最近研究一下JAVA中的顺序IO,在网络上找了一会儿,发现少有详细的介绍,顾此在此处说说顺序IO,才学疏浅,如有不对,望赐教。

什么是顺序IO

事实上JAVA具有很多操作文件的方案(方法), 许多程序需要将一些事件记录到本地存储中,常见的如数据库,MQ等,首先文件是许多带数据的块组成的,传统IO操作文件具有一个寻址过程(事实上硬件上也会存在寻道,旋转延迟等因素),小文件尚可,大文件就比较消耗性能和时间,比如数据库分配的文件(本地),顺序IO具备指定位置的功能,但是任然需要我们维护一个偏移量(游标).

MappedByteBuffer

JAVA顺序IO通过MappedByteBuffer实现,与传统IO不同的是,MappedByteBuffer需要使用者提供一个位置(偏移量),详细看以下代码:

mappedByteBuffer.position(index);
mappedByteBuffer.put(content.getBytes(StandardCharsets.UTF_8));

代码中可见,通过MappedByteBuffer提供的api position();来指定位置(偏移量),put()进行写操作,详细如下。

写操作

先看代码:

public int write(File file ,String content ,int index,long size){
RandomAccessFile randomAccessFile;
MappedByteBuffer mappedByteBuffer;
try { randomAccessFile = new RandomAccessFile(file,"rw"); //1
FileChannel fileChannel = randomAccessFile.getChannel(); //2
mappedByteBuffer = fileChannel.map(FileChannel.MapMode.READ_WRITE,0,size); //3 mappedByteBuffer.position(index); //4
mappedByteBuffer.put(content.getBytes(StandardCharsets.UTF_8)); //5
return mappedByteBuffer.position(); //6
}catch (Exception e){
e.printStackTrace();
}
return 0;
}
  • 上述代码中标注1位置中使用RandomAccessFile (随机流)来打开文件,此流与传统IO除了兼并读写之外,在一些底层实现方式上也均有不同,在此不多做介绍,感兴趣可另寻资料,在此需记住,此处使用随机流的作用为第二步做准备,且唯一,其中参数1为File对象,构造方法重载的参数1可为文件路径,参数2的取值可有4种,如下(取至JAVA官方文档):
  1. "r"仅供阅读。调用结果对象的任何写方法都会引发IOException。(Open for reading only. Invoking any of the write methods of the resulting object will cause an IOException to be thrown. )

  2. "rw"开放阅读和写作。如果该文件不存在,那么将尝试创建它。(Open for reading and writing. If the file does not already exist then an attempt will be made to create it. )

  3. “rws”和“rw”一样,对文件内容或元数据的每次更新都要同步写入底层存储设备。(Open for reading and writing, as with "rw", and also require that every update to the file's content or metadata be written synchronously to the underlying storage device. )

  4. “rwd”和“rw”一样,都是打开的,可以读写,并且还要求对文件内容的每次更新都要同步写入底层存储设备。(Open for reading and writing, as with "rw", and also require that every update to the file's content be written synchronously to the underlying storage device. )

  • 上述代码中标注2位置中,通过随机流获取到一个读写兼并的通道,实际上获取IO通道的方式并不仅仅只有此种方式,但是在此处需要注意的是,顺序读写所需的通道需兼并读写(第一步中参数2取值需为:rw,rws,rwd),如果不是,则会触发IO异常,除此之外,上述提到过使用其他方式也可以获取到文件IO通道,比如:
FileInputStream fileInputStream = new FileInputStream(file);
FileChannel fileChannel = fileInputStream.getChannel();

运行结果,标记3处抛出异常:NonWritableChannelException

或者:

FileOutputStream fileInputStream = new FileOutputStream(file);
FileChannel fileChannel = fileInputStream.getChannel();

运行结果,标记3处抛出异常:NonReadableChannelException

从上可以看到,不管是FileInputStream还是FileOutputStream获取到的IO通道,均有局限性,不适用MappedByteBuffer。

  • 上述代码中标记3位置中,通过IO通道将该文件的内容(或某个区域)直接映射到内存中,并且对该内存做的修改直接会传播到文件(除了PRIVATE模式,后续介绍),通过FileChannel对象的map();api进行映射,参数一指定映射方式,有如下三种(取至JAVA官方文档):
  1. 只读:任何修改结果缓冲区的尝试都将导致抛出ReadOnlyBufferException。(MapMode.READ_ONLY) (Read-only: Any attempt to modify the resulting buffer will cause a ReadOnlyBufferException to be thrown. (MapMode.READ_ONLY) )

  2. 读/写:对产生的缓冲区所做的更改最终将传播到文件;它们可能对映射了相同文件的其他程序可见,也可能不可见。(MapMode.READ_WRITE) (Read/write: Changes made to the resulting buffer will eventually be propagated to the file; they may or may not be made visible to other programs that have mapped the same file. (MapMode.READ_WRITE) )

  3. Private:对产生的缓冲区所做的更改不会传播到该文件中,并且不会对映射了该文件的其他程序可见;相反,它们将导致创建缓冲区修改部分的私有副本。(MapMode.PRIVATE) (Private: Changes made to the resulting buffer will not be propagated to the file and will not be visible to other programs that have mapped the same file; instead, they will cause private copies of the modified portions of the buffer to be created. (MapMode.PRIVATE) )

参数二代表从指定位置开始映射,0表示从头开始映射全部内容,参数三表示要映射的区域大小,可超出文件大小(如字符长度为3,此处可填写6或者其他),但不可为负数或超出Integer.MAX_VALUE.

实际上到此处,IO通道已经完成了它的任务,可关闭。(在标记3之后任意位置可执行fileChannel.close()而不影响运行结果)

此处简要说明了个参数的意思,要加深了解建议自己建立Demo并更改此处参数观察运行结果。

  • 上述代码中标记4位置中,通过MappedByteBuffer对象的position(); API设置写入位置,官方解释如下:

    Sets this buffer's limit. If the position is larger than the new limit then it is set to the new limit. If the mark is defined and larger than the new limit then it is discarded.

  • 上述代码中标记5位置中,将内容传输到缓冲区,可理解为写入,因为缓冲区的变动会传播到实际文件中,除了PRIVATE。

  • 上述代码中标记6位置中,返回下一次操作时的位置。

此篇文章简要说明了一下JAVA顺序IO,有些地方没有详细说明,会持续维护更新此篇文章,感谢大家。

关于JAVA中顺序IO的基本操作的更多相关文章

  1. java中的IO流

    Java中的IO流 在之前的时候我已经接触过C#中的IO流,也就是说集中数据固化的方式之一,那么我们今天来说一下java中的IO流. 首先,我们学习IO流就是要对文件或目录进行一系列的操作,那么怎样操 ...

  2. 深入理解Java中的IO

    深入理解Java中的IO 引言:     对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务 < Thinking in Java >   本文的目录视图如下: ...

  3. Java中的IO流(四)

    上一篇<Java中的IO流(三)>把IO流中的文件及目录操作的对象File类记录了一下,本篇把本不属性IO流但又和IO流有关系的一个对象作一下记录,此对象本属于集合框架里的一个子集,即Pr ...

  4. Java中的IO

    引言:     对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务 < Thinking in Java >   本文的目录视图如下:   Java IO概要 a ...

  5. Java NIO之Java中的IO分类

    前言 前面两篇文章(Java NIO之理解I/O模型(一).Java NIO之理解I/O模型(二))介绍了,IO的机制,以及几种IO模型的内容,还有涉及到的设计模式.这次要写一些更贴近实际一些的内容了 ...

  6. Java中的IO流之输入流|乐字节

    亲爱的乐字节的小伙伴们,小乐又来分享Java技术文章了.上一篇写到了IO流,这篇文章着重 谈谈输入流,再下次再说输出流. 点击回顾上一篇:乐字节Java之file.IO流基础知识和操作步骤 一. 输入 ...

  7. Java中的IO操作和缓冲区

    目录 Java中的IO操作和缓冲区 一.简述 二.IO流的介绍 什么是流 输入输出流的作用范围 三.Java中的字节流和字符流 字节流 字符流 二者的联系 1.InputStreamReader 2. ...

  8. java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET

    java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET 亲,“社区之星”已经一周岁了!      社区福利快来领取免费参加MDCC大会机会哦    Tag功能介绍—我们 ...

  9. java中的IO操作总结

    一.InputStream重用技巧(利用ByteArrayOutputStream) 对同一个InputStream对象进行使用多次. 比如,客户端从服务器获取数据 ,利用HttpURLConnect ...

随机推荐

  1. 从源码解析Electron的安装为什么这么慢

    前言 Electron作为一款跨平台的桌面应用端解决方案已经风靡全球.作为开发者,我们几乎不用关心与操作系统的交互,直接通过Web前端技术与Electron提供的API就可以完成桌面应用端的开发. 然 ...

  2. 前段之BOM ----DOM

    一.介绍 BOM(Browser Object Model)是指浏览器对象模型,它使 JavaScript 有能力与浏览器进行"对话". DOM (Document Object ...

  3. fastdfs单节点部署

    fastdfs单机版搭建 参考链接:https://blog.csdn.net/prcyang/article/details/89946190 搭建步骤 安装依赖 ​ yum -y install ...

  4. Python中pymongo find 遍历数据导致timeout

    背景 在读取大约200W左右的数据的时候采用游标形式进行数据遍历时,超过10分钟就报错 timeout 原因 pymongo游标会在10分钟之后被关闭 解决方案 db.find({}, no_curs ...

  5. Java(21)内部类

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15228411.html 博客主页:https://www.cnblogs.com/testero ...

  6. UI BLOCK自定义枚举控件的宽度

    三步: 1.修改PresentationStyle属性为Radio Box 2.修改NumberOfColumns属性为指定的宽度(显示字符的个数) 3.将PresentationStyle属性改回O ...

  7. 【JAVA】【作业向】第一题:本学期一班级有n名学生,m门课程。现要求对每门课程的成绩进行统计:平均成绩、最高成绩、最低成绩,并统计考试成绩的分布律。

    1.预备知识:动态数组Array实现: 2.解题过程需要理解的知识:吧唧吧唧吧唧吧唧 不想做了 就用了最简单的方法 和c语言类似 java版本 `import java.util.Scanner; / ...

  8. Golang通脉之函数

    函数是组织好的.可重复使用的.用于执行指定任务的代码块. Go语言中支持函数.匿名函数和闭包,并且函数在Go语言中属于"一等公民". 函数定义 Go语言中定义函数使用func关键字 ...

  9. Linux命令查看内存、整体负载、端口查看、进程查看、vim编辑器(3)

    一.资源占用命令   1.查看内存(free) free命令默认是以kb为单位显示的. free -m用Mb单位来显示. free -h显示单位 . free -h -s 3 ,每隔三秒刷新一次,如果 ...

  10. Linux信号处理编程

    01. 学习目标 了解信号中的基本概念 熟练使用信号相关的函数 了解内核中的阻塞信号集和未决信号集作用 熟悉信号集操作相关函数 熟练使用信号捕捉函数signal 熟练使用信号捕捉函数sigaction ...