关于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. SpringBoot 如何进行限流?老鸟们都这么玩的!

    大家好,我是飘渺.SpringBoot老鸟系列的文章已经写了四篇,每篇的阅读反响都还不错,那今天继续给大家带来老鸟系列的第五篇,来聊聊在SpringBoot项目中如何对接口进行限流,有哪些常见的限流算 ...

  2. 使用CEF(一)— 起步

    使用CEF(一)- 起步 介绍 Chromium Embedded Framework (CEF)是个基于Google Chromium项目的开源Web browser控件,支持Windows, Li ...

  3. 如何无缝迁移 SpringCloud/Dubbo 应用到 Serverless 架构

    作者 | 行松 阿里巴巴云原生团队 本文整理自<Serverless 技术公开课>,"Serverless"公众号后台回复"入门",即可获取系列文章 ...

  4. redis学习笔记-01 string类型命令

    一.set key value set joker 123456 #设定key为joker,value为123456的数据 二.keys * keys * #用于查看该数据库中所有的key值 三.se ...

  5. diff算法深入一下?

    文章转自豆皮范儿-diff算法深入一下 一.前言 有同学问:能否详细说一下 diff 算法. 简单说:diff 算法是一种优化手段,将前后两个模块进行差异化比较,修补(更新)差异的过程叫做 patch ...

  6. Go 语言实现 gRPC 的发布订阅模式,REST 接口和超时控制

    原文链接: 测试小姐姐问我 gRPC 怎么用,我直接把这篇文章甩给了她 上篇文章 gRPC,爆赞 直接爆了,内容主要包括:简单的 gRPC 服务,流处理模式,验证器,Token 认证和证书认证. 在多 ...

  7. RabbitMQ的一些理解和笔记

    在这篇博客中,简单记录一下 rabbitmq 服务器中一些基本的概念. Connection: connection 为 TCP连接,是我们的应用程序和RabbitMQ服务器真正发送和接收数据的地方. ...

  8. 【SDOI2014】数数(补)

    见 AC自动机(补坑了) [SDOI2014] 数数 简要题意:  我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为子串.例如当S={22,333,0233}时 ...

  9. binary-tree-maximum-path-sum leetcode C++

    Given a binary tree, find the maximum path sum. The path may start and end at any node in the tree. ...

  10. Windows7下面手把手教你安装Django - Hongten

    我所使用的操作系统是Windows7,内存是2G 在搜索了一些资料发现,对于Django的安装,详细的真的很少,都说的很简化,然而,这篇blog可以手把手教你成功安装Django 对于Django的详 ...