现有如下的一个需求,向已存在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

转载于:https://www.cnblogs.com/softidea/p/5122528.html

Java IO的RandomAccessFile的使用(转)相关推荐

  1. Java IO 4 : RandomAccessFile

    RandomAccessFile: 认识:java输入/输出流体系中功能最丰富的文件内容访问类 既可以读取文件内容,也可以向文件传输数据,并且支持"随机访问"的方式,程序可以跳转到 ...

  2. Java I/O流(二)——File,Properties,PrintWriter,IO ,RandomAccessFile,ByteBuffer,nio

    File概述 文件的操作是非常重要的,我们先来看下他的基本概念 •用于将文件或者文件夹封装成对象 •方便对文件和文件夹的操作 •File对象可以作为参数传递给流的构造函数 我们写个小例子先 impor ...

  3. JAVA IO - RandomAccessFile Seek学习

    2019独角兽企业重金招聘Python工程师标准>>> JAVA IO - RandomAccessFile Seek学习 import java.io.RandomAccessFi ...

  4. Java IO: RandomAccessFile

    转载自   Java IO: RandomAccessFile 译文链接 作者: Jakob Jenkov 译者: 李璟(jlee381344197@gmail.com) RandomAccessFi ...

  5. JAVA IO - RandomAccessFile

    2019独角兽企业重金招聘Python工程师标准>>> RandomAccessFile The RandomAccessFile class in the Java IO API ...

  6. java openfile busy_android java.io.IOException: open failed: EBUSY (Device or resource busy)

    今天遇到一个奇怪的问题, 测试在程序的下载界面,下载一个文件第一次下载成功,删除后再下载结果下载报错, 程序:file.createNewFile(); 报错:java.io.IOException: ...

  7. java urlconn 下载慢_使用HttpURLConnection下载文件时出现 java.io.FileNotFoundException彻底解决办法...

    import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAc ...

  8. [零基础学JAVA]Java SE应用部分-27.Java IO操作(01)

    JAVA IO操作目标 本季知识点 1.File类 2.RandomAccessFile类 File类 在JAVA中所有的IO操作全部存放在java.io包中. File是唯一一个与文件本身有关的操作 ...

  9. Java IO 性能优化大PK,什么场景用啥,都给你总结好啦!

    作者:莫那·鲁道 ,来自:http://thinkinjava.cn 前言 Java 在 JDK 1.4 引入了 ByteBuffer 等 NIO 相关的类,使得 Java 程序员可以抛弃基于 Str ...

最新文章

  1. 这50位青年科学家,腾讯每人给300万
  2. 骗子防不胜防,我们该如何安全上网?
  3. c# 2.0 Factory的实现
  4. 线程并发编程之线程锁
  5. 申请计算机助理的英语作文,有关于应聘团队助理的申请信的英语作文要有中文翻译...
  6. SVN工作笔记005---TortoiseSVN SendRpt.exe not found解决方案
  7. 美国女童子军正在学习电脑黑客技术!
  8. ubuntu 文件权限命令详解使用格式和方法
  9. 最新快手面试题(含总结):设计模式+红黑树+Java锁+Redis等
  10. LNMP源码安装教程
  11. Java反编译工具XJad使用注意事项
  12. (MTT)连续能量函数最小化方法
  13. DRM in Android详解--转
  14. 设置linux kernel 日志打印方法
  15. windows服务器漏洞修复,Windows7系统漏洞怎么修复?
  16. 27岁研究生毕业年龄大吗?
  17. android7 显示到pc,安卓手机上的画面怎么投屏到Win7电脑上?超详细投屏方法看这里!...
  18. java 字符串很长_String:java:常量字符串过长
  19. Vue-cli使用prerender-spa-plugin插件预渲染的问题
  20. go实现dgraph的各种操作

热门文章

  1. 从零开发一个命令行脚手架工具 等
  2. 小姐姐笔记:我是如何学习简单源码拓展视野的
  3. 【php复习之】php创建数组的几种方式
  4. 线程管理(九)使用本地线程变量
  5. avalon2学习教程15指令总结
  6. 关于Android studio找不到sqlite数据库的解决方法
  7. Anaconda+vscode+pytorch环境搭建
  8. webpack常用配置
  9. bzoj3122 [Sdoi2013]随机数生成器(bsgs+扩欧+数列)
  10. bzoj2721 [Violet 5]樱花