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

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

关于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官⽅⽂档):
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,有些地⽅没有详细说明,会持续维护更新此篇⽂章,感谢⼤家。

相关文档
最新文档