关于JAVA中顺序IO的基本操作
关于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官方文档):
"r"仅供阅读。调用结果对象的任何写方法都会引发IOException。(Open for reading only. Invoking any of the write methods of the resulting object will cause an IOException to be thrown. )
"rw"开放阅读和写作。如果该文件不存在,那么将尝试创建它。(Open for reading and writing. If the file does not already exist then an attempt will be made to create it. )
“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. )
“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官方文档):
只读:任何修改结果缓冲区的尝试都将导致抛出ReadOnlyBufferException。(MapMode.READ_ONLY) (Read-only: Any attempt to modify the resulting buffer will cause a ReadOnlyBufferException to be thrown. (MapMode.READ_ONLY) )
读/写:对产生的缓冲区所做的更改最终将传播到文件;它们可能对映射了相同文件的其他程序可见,也可能不可见。(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) )
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的基本操作的更多相关文章
- java中的IO流
Java中的IO流 在之前的时候我已经接触过C#中的IO流,也就是说集中数据固化的方式之一,那么我们今天来说一下java中的IO流. 首先,我们学习IO流就是要对文件或目录进行一系列的操作,那么怎样操 ...
- 深入理解Java中的IO
深入理解Java中的IO 引言: 对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务 < Thinking in Java > 本文的目录视图如下: ...
- Java中的IO流(四)
上一篇<Java中的IO流(三)>把IO流中的文件及目录操作的对象File类记录了一下,本篇把本不属性IO流但又和IO流有关系的一个对象作一下记录,此对象本属于集合框架里的一个子集,即Pr ...
- Java中的IO
引言: 对程序语言的设计者来说,创建一个好的输入/输出(I/O)系统是一项艰难的任务 < Thinking in Java > 本文的目录视图如下: Java IO概要 a ...
- Java NIO之Java中的IO分类
前言 前面两篇文章(Java NIO之理解I/O模型(一).Java NIO之理解I/O模型(二))介绍了,IO的机制,以及几种IO模型的内容,还有涉及到的设计模式.这次要写一些更贴近实际一些的内容了 ...
- Java中的IO流之输入流|乐字节
亲爱的乐字节的小伙伴们,小乐又来分享Java技术文章了.上一篇写到了IO流,这篇文章着重 谈谈输入流,再下次再说输出流. 点击回顾上一篇:乐字节Java之file.IO流基础知识和操作步骤 一. 输入 ...
- Java中的IO操作和缓冲区
目录 Java中的IO操作和缓冲区 一.简述 二.IO流的介绍 什么是流 输入输出流的作用范围 三.Java中的字节流和字符流 字节流 字符流 二者的联系 1.InputStreamReader 2. ...
- java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET
java中的io系统详解 - ilibaba的专栏 - 博客频道 - CSDN.NET 亲,“社区之星”已经一周岁了! 社区福利快来领取免费参加MDCC大会机会哦 Tag功能介绍—我们 ...
- java中的IO操作总结
一.InputStream重用技巧(利用ByteArrayOutputStream) 对同一个InputStream对象进行使用多次. 比如,客户端从服务器获取数据 ,利用HttpURLConnect ...
随机推荐
- JS中call,apply,bind的区别
1.关于this对象的指向,请看如下代码 var name = 'jack'; var age = 18; var obj = { name:'mary', objAge:this.age, myFu ...
- 开启Nginx代理HTTPS功能
1.首先查看是否已经安装SSL openssl version -a 2.生成SSL证书 在nginx目录下创建ssl文件夹 cd /etc/pki mkdir nginx cd nginx 生成20 ...
- 听说,99% 的 Go 程序员都被 defer 坑过
原文链接: 听说,99% 的 Go 程序员都被 defer 坑过 先声明:我被坑过. 之前写 Go 专栏时,写过一篇文章:Go 专栏|错误处理:defer,panic 和 recover.有小伙伴留言 ...
- Frida高级逆向-Hook Java
Frida Hook Java 层 Frida两种启动方式的区别 span 模式:frida 重新打开一个进程 frida -U -f 包名 -l js路径 --no-pause attch 模式: ...
- CentOS 压缩解压
目录 命令 tar gzip.gunzip bzip2.bunzip2 zip.unzip 命令组合 打包:将多个文件合成一个总的文件,这个总的文件通常称为"归档". 压缩:将一个 ...
- BUAA 2020 软件工程 结对项目作业
Author: 17373051 郭骏 3.28添加:4.计算模块接口的设计与实现过程部分,PairCore实现的细节 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) ...
- JavaAgent型内存马基础
Java Instrumentation java Instrumentation指的是可以用独立于应用程序之外的代理(agent)程序来监测和协助运行在JVM上的应用程序.这种监测和协助包括但不 ...
- Noip模拟77 2021.10.15
T1 最大或 $T1$因为没有开$1ll$右移给炸掉了,调了一年不知道为啥,最后实在不懂了 换成$pow$就过掉了,但是考场上这题耽误了太多时间,后面的题也就没办法好好打了.... 以后一定要注意右移 ...
- geos编译问题
gdal编译geos的时候会用到geos_c_i.lib这个文件,我用cmake编译的时候仅仅产生geos_c.lib这个文件,所以只能使用nmake的编译方式来编译geos库,nmake编译geos ...
- 21.6.23 test
省选 模拟赛 今天考的是一套题目背景和描述会被[数据删除]的模拟赛. 犯了几个傻逼错. \(T1\) 把两种情况的概率看反了,写的暴力.\(35->5\) pts. \(T2\) 以为想到了正解 ...