RandomAccessFile
RandomAccessFile 是随机访问文件的类. 它支持对文件随机访问的读取和写入, 即我们也可以从指定的位置读取 / 写入文件数据, 因为该类在其内部封装了一个数组和指针, 当要用该类的对象读取文件中的元素时, 就将要读取的元素先存储在数组中, 而 get 方法和 set 方法也就是读和写操作.
需要注意的是, RandomAccessFile 虽然属于 java.io 包(因为它具备读和写的功能), 但它不是 InputStream 或者 OutputStream 的子类; FileInputStream 只能对文件进行读操作, 而 FileOutputStream 只能对文件进行写操作; 但是, RandomAccessFile 同时支持文件的读和写, 并且它支持随机访问, 原理在于 RandomAccessFile 内部封装了 FileInputStream 和 FileOutputStream.
虽然 RandomAccessFile 可以同时对文件进行读取和写入, 但是它却有一个较大的局限性, 那就是它只能操作文件, 也就是说只能操作硬盘上的数据, 而不能操作内存, 控制台上的数据.
构造函数:
1. RandomAccessFile 模式说明
RandomAccessFile 共有 4 种模式:"r", "rw", "rws" 和 "rwd".
"r" 以只读方式打开. 调用结果对象的任何 write 方法都将导致抛出 IOException.
"rw" 打开以便读取和写入. 如果该文件尚不存在, 则尝试创建该文件.
"rws" 打开以便读取和写入. 相对于 "rw","rws" 还要求对 "文件的内容" 或 "元数据" 的每个更新都同步写入到基础存储设备.
"rwd" 打开以便读取和写入, 相对于 "rw","rwd" 还要求对 "文件的内容" 的每个更新都同步写入到基础存储设备.
说明:
(01) 什么是 "元数据", 即 metadata?
metadata 是 "关于数据的数据". 在文件系统中, 数据被包含在文件和文件夹中; metadata 信息包括:"数据是一个文件, 一个目录还是一个链接","数据的创建时间(简称 ctime)","最后一次修改时间(简称 mtime)","数据拥有者","数据拥有群组","访问权限" 等等.
(02) "rw", "rws", "rwd" 的区别.
当操作的文件是存储在本地的基础存储设备上时(如硬盘, NandFlash 等),"rws" 或 "rwd", "rw" 才有区别.
当模式是 "rws" 并且 操作的是基础存储设备上的文件; 那么, 每次 "更改文件内容 [如 write() 写入数据]" 或 "修改文件元数据(如文件的 mtime)" 时, 都会将这些改变同步到基础存储设备上.
当模式是 "rwd" 并且 操作的是基础存储设备上的文件; 那么, 每次 "更改文件内容 [如 write() 写入数据]" 时, 都会将这些改变同步到基础存储设备上.
当模式是 "rw" 并且 操作的是基础存储设备上的文件; 那么, 关闭文件时, 会将 "文件内容的修改" 同步到基础存储设备上. 至于,"更改文件内容" 时, 是否会立即同步, 取决于系统底层实现.
注意: 该对象在实例化时, 如果要操作的文件不存在, 不管是读操作还是写操作, 都会自动创建文件; 如果文件存在, 写数据时未指定位置, 会从头开始写, 即覆盖原有的内容(注意只覆盖自己写入的位置). 可以用于多线程下载或多个线程同时写数据到文件.
[代码演示]
- import java.io.IOException;
- import java.io.RandomAccessFile;
- public class RandomAccessFileWriteDemo {
- public static void main(String[] args)throws IOException {
- RandomAccessFile rafw=new RandomAccessFile("c:\\html\\test\\r.txt","rw");
- // 文件不存在, 则自动创建, 当文件存在时, 会覆盖原有的文件, 注意只是覆盖自己写入的部分.
- rafw.write("sdfghjk".getBytes());// 注意要进行写操作时, 构造函数的 mode 必须设置为 rw, 否则报错: 拒绝访问.
- //rafw.writeInt(17);// 注意 write 方法只写入最低八位, 会造成数据丢失, 因此选用 writeInt 方法
- rafw.close();
- RandomAccessFile rafr=new RandomAccessFile("c:\\html\\test\\r.txt","rw");
- rafr.seek(3);// 可以调节指针的位置, 传入 3, 则表示从三号位置开始读取, 默认指针是从 0 开始
- byte[] buff=new byte[8];
- int num;
- while ((num=rafr.read(buff))!=-1){
- System.out.print(new String(buff,0,num));
- }
- rafr.close();
- }
- }
[代码演示] : 往文件的指定位置插入内容, 且不能覆盖原来的内容.
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.RandomAccessFile;
- import java.util.Scanner;
- public class insertData {
- public static void main(String[] args) {
- Scanner in=new Scanner(System.in);
- System.out.println("请输入文件存放的路径:");
- String path=in.nextLine();
- System.out.println("请输入要插入的位置:");
- Long points=in.nextLong();
- in.nextLine();// 缓冲回车键
- System.out.println("请输入要插入的内容:");
- String insertContent=in.nextLine();
- try{
- randomInserst(path,points,insertContent);
- }catch (IOException e){
- System.out.println("插入失败");
- }
- }
- public static void randomInserst(String path,Long points,String insertContent)throws IOException {
- RandomAccessFile raf=new RandomAccessFile(path,"rw");
- raf.seek(points);// 调节指针位置
- FileOutputStream fos=new FileOutputStream("c:\\html\\test\\tmp.txt");// 临时文件
- byte[] buff=new byte[12];
- int num;
- while ((num=raf.read(buff))!=-1){// 将指针后面的内容先存储到临时文件中
- fos.write(buff,0,num);// 避免脏读
- }
- raf.seek(points);// 因为指针会随着读取数据移动, 最终到末尾, 所以要重新调节指针位置
- raf.writeBytes(insertContent);// 将要写的内容插入
- FileInputStream fis=new FileInputStream("c:\\html\\test\\tmp.txt");// 读取临时文件
- byte[] buff2=new byte[12];
- int num2;
- while ((num2=fis.read(buff2))!=-1){// 将指针后面的内容先存储到临时文件中
- raf.write(buff2,0,num2);
- }
- fis.close();
- fos.close();
- raf.close();
- }
- }
来源: http://www.bubuko.com/infodetail-3438111.html