现有如下的一个需求,向已存在1G数据的txt文本里末尾追加一行文字,内容如下“Lucene是一款非常优秀的全文检索库”。可能大多数朋友会觉得这个需求很easy,说实话,确实easy,然后XXX君开始实现了,直接使用Java中的流读取了txt文本里原来所有的数据转成字符串后,然后拼接了“Lucene是一款非常优秀的全文检索库”,又写回文本里了,至此,大功告成。后来需求改了,向5G数据的txt文本里追加了,结果XXX君傻了,他内存只有4G,如果强制读取所有的数据并追加,会报内存溢出的异常。

其实上面的需求很简单,如果我们使用JAVA IO体系中的RandomAccessFile类来完成的话,可以实现零内存追加。其实这就是支持任意位置读写类的强大之处。

RandomAccessFile是Java中输入,输出流体系中功能最丰富的文件内容访问类,它提供很多方法来操作文件,包括读写支持,与普通的IO流相比,它最大的特别之处就是支持任意访问的方式,程序可以直接跳到任意地方来读写数据。

如果我们只希望访问文件的部分内容,而不是把文件从头读到尾,使用RandomAccessFile将会带来更简洁的代码以及更好的性能。

下面来看下RandomAccessFile类中比较重要的2个方法,其他的和普通IO类似,在这里,就不详细说明了。

方法名 作用
getFilePointer() 返回文件记录指针的当前位置
seek(long pos) 将文件记录指针定位到pos的位置

功能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这个类,来实现一个多线程断点下载的功能,用过下载工具的朋友们都知道,下载前都会建立两个临时文件,一个是与被下载文件大小相同的空文件,另一个是记录文件指针的位置文件,每次暂停的时候,都会保存上一次的指针,然后断点下载的时候,会继续从上一次的地方下载,从而实现断点下载或上传的功能,有兴趣的朋友们可以自己实现下。

http://blog.csdn.net/czplplp_900725/article/details/37809579

Java IO的RandomAccessFile的使用(转)的更多相关文章

  1. Java—IO流 RandomAccessFile类

    RandomAccessFile java提供的对文件内容的访问,既可以读文件,也可以写文件. 支持随机访问文件,可以访问文件的任意位置. java文件模型,在硬盘上的文件是byte byte byt ...

  2. Java IO 之 RandomAccessFile 操作文件内容

    RandomAccessFile类实现对文件内容的随机读写 文件内容的随机操作,重难点在于字符操作,具体查看API package org.zln.io.file; import java.io.IO ...

  3. Java IO学习--RandomAccessFile

    1.什么是 随机访问文件流 RandomAccessFile 这个类在很多资料上翻译成中文都是:随机访问文件,在中文里,随机是具有不确定的含义,指一会访问这里,一会访问那里的意思.如果以这种语义来解释 ...

  4. Java IO(二)--RandomAccessFile基本使用

    RandomAccessFile: 翻译过来就是任意修改文件,可以从文件的任意位置进行修改,迅雷的下载就是通过多个线程同时读取下载文件.例如,把一个文件分为四 部分,四个线程同时下载,最后进行内容拼接 ...

  5. Java IO系统--RandomAccessFile

    RandomAccessFile 实现了DataOutput接口和DataInput接口.父类是Object,不继承任何的InputStream和OutStram. public class Rand ...

  6. java io系列26之 RandomAccessFile

    本文主要介绍 RandomAccessFile. 转载请注明出处:http://www.cnblogs.com/skywang12345/p/io_26.html 更多内容请参考:java io系列0 ...

  7. Java IO流学习

    Java IO流学习 Java流操作有关的类或接口: Java流类图结构: 流的概念和作用 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的总称或抽象.即数据在两设备间的传输称为流,流的本质是 ...

  8. [Java IO]01_File类和RandomAccessFile类

    File类 File类是java.io包中唯一对文件本身进行操作的类.它可以进行创建.删除文件等操作.   File类常用操作 (1)创建文件 可以使用 createNewFille() 创建一个新文 ...

  9. Java IO RandomAccessFile 任意位置读/写

    随机读写类 RandomAccessFile的唯一父类是Object,与其他流父类不同.是用来访问那些保存数据记录的文件的,这样你就可以用seek( )方法来访问记录,并进行读写了.这些记录的大小不必 ...

随机推荐

  1. Bootstrap网站模板

    根据一篇文章,我再想想写下,无意义,他决定收手. 或者直接做一个简单的基本的模板它 主要知识点包含栅格系统.响应式图片.导航条(固定在顶部和底部).搜索框等等 详细每一个知识点不再赘述,參考Boots ...

  2. FZU2082

    树链剖分后要处理的是边的权值,而不是点的权值,但是只要边权下放到点,就可以了 如图 但是问题是,求图4->5路径的权值之和, 那么就会把点3给算进去 那么就要减去, 或者干脆不加进去 有两种方法 ...

  3. 如何解决Windows8.1(32bit&64bit)下Cisco VPN Client拨号时报442错误的问题

    Cisco VPN Cient大多数网络管理员.技术支持project最流行的教师和最终用户VPNclient一间.对于外部网络访问内部网络,技术类人员. 随着Windows8.1的推出.Cisco ...

  4. 状态压缩dp入门

    poj1321 http://poj.org/problem?id=1321 我们可以把棋盘的每一行看做是一个状态,如果某一列放置了棋子,那么就标记为1,否则就标记为0.然后把它看成是一个二进制数,然 ...

  5. extjs的相关属性

    通用属性: labelSeparator:''//表示fieldLabel后不会显示冒号":" readOnly:true//仅仅读 focusCls: 'txtHalfInput ...

  6. CSDN挑战编程——《金色十月线上编程比赛第二题:解密》

    金色十月线上编程比赛第二题:解密 题目详情: 小强是一名学生, 同一时候他也是一个黑客. 考试结束后不久.他吃惊的发现自己的高等数学科目竟然挂了,于是他果断入侵了学校教务部站点. 在入侵的过程中.他发 ...

  7. WCF-001:WCF的发布

    随着“云”时代的到来,“云”已经无处不在了.什么是“云”,无非就是利用互联网强大的功能建立多个服务器,然后再利用互联网的传输数据的特点将数据从某个服务器中读取出来或者将你的数据上传上去.当然这个服务器 ...

  8. 微渠道发展 BAE交通运输平台和java呼声,微信mysql数据库开发实例 --图文开发教程

    持续更新 BAE java开展mysql数据库 图文教程 BAE java语言发展mysql源码下载: 目前微信的发展.BAE开展.java开展.mysql教程开发非常,的介绍基于BAE平台.java ...

  9. 使用 Cordova+Visual Studio 创建跨平台移动应用(3)

    1 背景 本章节是关于Telerik AppBuilder for Visual Studio的. 目前(2014.12)为Telerik公司Telerik Platform的一部分,Telerik ...

  10. 剑指offer 例题

    题目: 实现一个排序算法,排序对象是本公司员工的年龄.要求时间复杂度O(n),空间复杂度不能超过O(n). #include<iostream> using namespace std; ...