Java 实现文件随机读写-RandomAccessFile
现有如下的一个需求,向已存在1G数据的txt文本里末尾追加一行文字,内容如下“Lucene是一款非常优秀的全文检索库”。可能大多数朋友会觉得这个需求很easy,说实话,确实easy,然后XXX君开始实现了,直接使用Java中的流读取了txt文本里原来所有的数据转成字符串后,然后拼接了“Lucene是一款非常优秀的全文检索库”,又写回文本里了,至此,大功告成。后来需求改了,向5G数据的txt文本里追加了,结果XXX君傻了,他内存只有4G,如果强制读取所有的数据并追加,会报内存溢出的异常。
其实上面的需求很简单,如果我们使用JAVA IO体系中的RandomAccessFile类来完成的话,可以实现零内存追加。其实这就是支持任意位置读写类的强大之处。
在这之前,还是先啰嗦的介绍下RandomAccessFile这个类,RandomAccessFile是Java中输入,输出流体系中功能最丰富的文件内容访问类,它提供很多方法来操作文件,包括读写支持,与普通的IO流相比,它最大的特别之处就是支持任意访问的方式,程序可以直接跳到任意地方来读写数据。
如果我们只希望访问文件的部分内容,而不是把文件从头读到尾,使用RandomAccessFile将会带来更简洁的代码以及更好的性能。
下面来看下RandomAccessFile类中比较重要的2个方法,其他的和普通IO类似,在这里,就不详细说明了。
方法名 | 作用 |
getFilePointer() | 返回文件记录指针的当前位置 |
seek(long pos) | 将文件记录指针定位到pos的位置 |
下面散仙给出示例,分析下怎么使用RandomAccessFile
首先,我们先看下要操作的文本文件的内容截图。
功能one,读取任意位置的数据,代码如下
- /**
- * 读的方法
- * @param path 文件路径
- * @param pointe 指针位置
- * **/
- public static void randomRed(String path,int pointe){
- try{
- //RandomAccessFile raf=new RandomAccessFile(new File("D:\\3\\test.txt"), "r");
- /**
- * model各个参数详解
- * r 代表以只读方式打开指定文件
- * rw 以读写方式打开指定文件
- * rws 读写方式打开,并对内容或元数据都同步写入底层存储设备
- * rwd 读写方式打开,对文件内容的更新同步更新至底层存储设备
- *
- * **/
- RandomAccessFile raf=new RandomAccessFile(path, "r");
- //获取RandomAccessFile对象文件指针的位置,初始位置是0
- System.out.println("RandomAccessFile文件指针的初始位置:"+raf.getFilePointer());
- raf.seek(pointe);//移动文件指针位置
- byte[] buff=new byte[1024];
- //用于保存实际读取的字节数
- int hasRead=0;
- //循环读取
- while((hasRead=raf.read(buff))>0){
- //打印读取的内容,并将字节转为字符串输入
- System.out.println(new String(buff,0,hasRead));
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- }
测试代码
- public static void main(String[] args) {
- String path="D:\\3\\test.txt";
- int seekPointer=20;
- randomRed(path,seekPointer);//读取的方法
- //randomWrite(path);//追加写的方法
- //insert(path, 33, "\nlucene是一个优秀的全文检索库");
- }
运行效果:
- RandomAccessFile文件指针的初始位置:0
- is a teacher
- hadoop is perfect
功能two,追加数据,代码如下
- /**
- * 追加方式
- * 写的方法
- * @param path 文件路径
- * ***/
- public static void randomWrite(String path){
- try{
- /**以读写的方式建立一个RandomAccessFile对象**/
- RandomAccessFile raf=new RandomAccessFile(path, "rw");
- //将记录指针移动到文件最后
- raf.seek(raf.length());
- raf.write("我是追加的 \r\n".getBytes());
- }catch(Exception e){
- e.printStackTrace();
- }
- }
测试代码
- public static void main(String[] args) {
- String path="D:\\3\\test.txt";
- //int seekPointer=20;
- // randomRed(path,seekPointer);//读取的方法
- randomWrite(path);//追加写的方法
- //insert(path, 33, "\nlucene是一个优秀的全文检索库");
- }
运行效果:
功能three,任意位置插入数据,代码如下
- /**
- * 实现向指定位置
- * 插入数据
- * @param fileName 文件名
- * @param points 指针位置
- * @param insertContent 插入内容
- * **/
- public static void insert(String fileName,long points,String insertContent){
- try{
- File tmp=File.createTempFile("tmp", null);
- tmp.deleteOnExit();//在JVM退出时删除
- RandomAccessFile raf=new RandomAccessFile(fileName, "rw");
- //创建一个临时文件夹来保存插入点后的数据
- FileOutputStream tmpOut=new FileOutputStream(tmp);
- FileInputStream tmpIn=new FileInputStream(tmp);
- raf.seek(points);
- /**将插入点后的内容读入临时文件夹**/
- byte [] buff=new byte[1024];
- //用于保存临时读取的字节数
- int hasRead=0;
- //循环读取插入点后的内容
- while((hasRead=raf.read(buff))>0){
- // 将读取的数据写入临时文件中
- tmpOut.write(buff, 0, hasRead);
- }
- //插入需要指定添加的数据
- raf.seek(points);//返回原来的插入处
- //追加需要追加的内容
- raf.write(insertContent.getBytes());
- //最后追加临时文件中的内容
- while((hasRead=tmpIn.read(buff))>0){
- raf.write(buff,0,hasRead);
- }
- }catch(Exception e){
- e.printStackTrace();
- }
- }
测试代码
- public static void main(String[] args) {
- String path="D:\\3\\test.txt";
- //int seekPointer=20;
- // randomRed(path,seekPointer);//读取的方法
- // randomWrite(path);//追加写的方法
- insert(path, 33, "\nlucene是一个优秀的全文检索库");
- }
运行效果:
至此,RandomAccessFile类的几个功能,散仙在代码中已给出实现了,现在回到本文开始前的提的那个需求,用RandomAccessFile类就可以轻而易举的完成了,另外需要注意的是,向指定位置插入数据,是散仙自己改造的功能,RandomAccessFile并不直接支持,需要新建一个缓冲区临时空间,存数据,然后在写,因为一旦数据量上了级别,在任意位置插入数据,是很耗内存的,这个也就是为什么hadoop的HDFS文件系统,只支持append的方式,而没有提供修改的操作。
另外我们可以用RandomAccessFile这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。
Java 实现文件随机读写-RandomAccessFile的更多相关文章
- 从零开始学C++之IO流类库(三):文件的读写、二进制文件的读写、文件随机读写
一.文件的读写 如前面所提,流的读写主要有<<, >>, get, put, read, write 等操作,ofstream 继承自ostream, ifstream 继承自 ...
- 营销MM让我讲MySQL日志顺序读写及数据文件随机读写原理
摘要:你知道吗,MySQL在实际工作时候的两种数据读写机制? 本文分享自华为云社区<MySQL日志顺序读写及数据文件随机读写原理>,作者:JavaEdge . MySQL在实际工作时候的两 ...
- 文件随机读写专用类——RandomAccessFile
RandomAccessFile类可以随机读取文件,但是在测试中并不好用;File类可以测试文件存不存在,不存在可以创建文件;FileWriter类可以对文件进行重写或者追加内容;FileReade ...
- Java实现文件的读写,复制
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileInputStr ...
- java字符文件的读写
1.java文件读写,首先我们需要导入相应的包:java.io.*; 2.代码如下: package Demo1; import java.io.*; public class FileWirteTe ...
- Java实现文件的读写
需求:实现基本的读写 package com.sbx.io; import java.io.File; import java.io.FileReader; import java.io.FileWr ...
- 第9.9节 Python文件随机读写定位操作方法seek
类似于C语言,Python也提供了文件位置定位的操作方法seek. 一. 语法 seek(offset, whence=SEEK_SET) 语法释义: 1)offset :将文件当前操作位置移动偏移量 ...
- java 实现文件读写操作
import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; /* JAVA IO 读写操作 20 ...
- java中文件的I/O操作
java中文件的读写操作 (一) (1)java中文件的字节转成字符读操作 FileInputStream fStream = new FileInputStream("test.txt&q ...
随机推荐
- Ubuntu下修改tomcat6默认的8080端口
$ sudo vi /etc/tomcat6/server.xml 将 <Connector port="8080" protocol="HTTP/1.1&qu ...
- 【活动】上线了|带你直击react年度盛会
明后两天,ReactEurope 2016大会在巴黎举行,本次大会演讲主题有: React Native(动画及运行性能优化) Flux-like 数据架构(GraphQL 最佳实践与展望.Redux ...
- Expectation Maximization(EM)算法note
EM算法,之前上模式识别课上,推导过,在<统计学习方法>中没耐性的看过几次,个人感觉讲的过于理论,当时没怎么看懂,后来学lda,想要自己实现一下em算法,又忘记了,看来还是学的不够仔细,认 ...
- java 获取服务器时间同步本地计算机时间
http://hi.baidu.com/captives/item/25c8b80170a9b0ccf45ba6f8 ————————————————————————————————————————— ...
- 【PM面试题】设计一个股价推送工具
这一轮面试时间比较短,问题在短时间内不能很全面展开,因此抓住一些关键点变得尤其重要,这里我记录下当时是怎么想这个问题的. 问题解析 子问题1:推送什么?从问题中看出我们需要推送的是股价,用户可以自定义 ...
- 第二百四十三节,Bootstrap模态框插件
Bootstrap模态框插件 学习要点: 1.基本使用 2.用法说明 本节课我们主要学习一下 Bootstrap 中的模态框插件,这是一款交互式网站非常常见的 弹窗功能插件. 一.基本使用 使用模态框 ...
- 第一百四十二节,JavaScript,封装库--运动动画和透明度动画
JavaScript,封装库--运动动画和透明度动画 /** yi_dong_tou_ming()方法,说明 * * yi_dong_tou_ming()方法,将一个元素,进行一下动画操作 * 1,x ...
- char类型能否存储一个中文字符?为什么
char类型能否存储一个中文字符?为什么 解答:可以.一个char是两个字节,而一个中文也是两个字节.
- LigerTree的使用
效果图: 页面: <div id="divs" style="width: 310px; overflow-x: hidden; overflow-y: hidde ...
- Http服务器实现文件上传与下载(四)
一.引言 欢迎大家来到和我一起编写Http服务器实现文件的上传和下载,现在我稍微回顾一下之前我说的,第一.二章说明说明了整体的HTTP走向,第三章实现底层的网络编程.接着这一章我想给大家讲的是请求获取 ...