JavaIO流RandomAccessFile类

7次阅读

共计 3013 个字符,预计需要花费 8 分钟才能阅读完成。

一、前言

  • 文件的读取或存储信息主要有两种方式:

    • 通过输入输出流,即InputStream、OutputStream
    • 通过RandomAccessFile
  • RandomAccessFile是一个完全独立的类,RandomAccessFile 虽然属于 java.io 包,但其拥有和我们认识的其它的 IO 类型有本质不同的行为,可以在一个文件内向前和向后移动。

二、作用说明

  • 2.1、作用:RandomAccessFile 同时支持文件的读和写,并且它支持随机访问。是通过文件指针实现的

    • 看一下其主要方法

       void write(int d) // 向文件中写入 1 个字节,写入的是传入的 int 值对应二进制的低 8 位;void write(int b) // 往文件中写入 1 个字节的内容,所写的内容为传入的 int 值对应二进制的低 8 位;write(byte b[])   // 往文件中写入一个字节数组的内容;write(byte b[], int off, int len) // 往文件中写入从数组 b 的下标 off 开始 len 个字节的内容;int read()        // 读取 1 个字节,并以 int 形式返回,如果返回 - 1 则代表已到文件末尾;int read(byte[] data) /* 一次性从文件中读取字节数组总长度的字节量,并存入到该字节数组中,返回的 int 值代表读入的总字节数,如果返回 - 1 则代表未读取到任何数据。通常字节数组的长度可以指定为 1024*10(大概 10Kb 的样子,效率比较好);*/
       int read(byte[] data, int off, int len) /* 一次性从文件中读取最多 len 个字节,并存入到 data 数组中,从下标 off 处开始;*/
      
       seek (long pos)   // 设置文件指针偏移量为指定值,即在文件内移动至新的位置;long getFilePointer() // 获取文件指针的当前位置;void close()     // 关闭 RandomAccessFile;
  • 2.2、访问模式

    • “r”:以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
    • “rw”:打开以便读取和访问,如果文件不存在则创建文件。
    • “rws”:打开以便读取和写入。相对于 “rw”,”rws” 还要求对“文件的内容”或“元数据”的每个更新都同步写入到基础存储设备。
    • “rwd”:打开以便读取和写入,相对于 “rw”,”rwd” 还要求对“文件的内容”的每个更新都同步写入到基础存储设备。
    • 说明:"rw", "rws", "rwd" 的区别

      • 当操作的文件是存储在本地的 基础存储设备 上时(如硬盘, NandFlash 等),”rws” 或 “rwd”, “rw” 才有区别。当操作的是基础存储设备上的文件时:如下

        • rws:每次“更改文件内容 [如write() 写入数据 ]”或“ 修改文件元数据 (如文件的 mtime)”时,都会将这些改变 同步 到基础存储设备上。
        • rwd:每次“更改文件内容 [如write() 写入数据 ]”时,都会将这些改变 同步 到基础存储设备上。
        • rw:关闭文件时 ,会将“文件内容的修改” 同步 到基础存储设备上。至于,“更改文件内容”时,是否会立即同步,取决于 系统底层实现。
  • 2.3、demo

    • 2.3.1 工作方式

      • (1)、把 DataInputStream 和 DataOutputStream 结合起来
      • (2)、再加上它自己的一些方法,比如定位用的 getFilePointer(),在文件里移动用的 seek()
      • (3)、以及判断文件大小的 length()、skipBytes()跳过多少字节数
    • 2.3.2、构造函数:RandomAccessFile(File file/String filename, "model");

      //demo01:_
      File file = new File("data.txt");
      try (RandomAccessFile raf = new RandomAccessFile(file, "rw");){raf.write(1000);    // 这里写入一个字节(1000 对应二进制的低八位)raf.seek(0);        // 跳到文件头部
          System.Out.println(raf.read());// 输出:232
          raf.seek(0);        // 跳到文件头部
          System.out.println(raf.readInt());// 试图读取一个整数,字节数不够
      }catch (IOException e){e.printStackTrace();
       }
      • 注意:RandomAccessFile 是基于文件指针从 当前位置 来读写的,并且写入操作是直接将插入点后面的内容 覆盖 而不是插入。如果我们想实现插入操作,则需要将插入点后面的内容先 保存 下来,再写入要插入的内容,最后将保存的内容添加进来。下面这个例子很有趣
    //demo02:_向文件中间追加内容。记住是中间
    try(File file = new File("data2.txt");
           RandomAccessFile raf = new RadnomAccessFile(file, "rw");
           // 创建临时空文件用于缓冲,并指定在虚拟机停止时将其删除
           File temp = File.createTempFile("temp", null);){temp.deleteOnExit();
        
        raf.seek(0); 
        raf.write("烟村四五家".getBytes());
        raf.seek(0); 
        long dataLen = "烟村四五家".length();    // 获取文件当前长度
        byte[] data1 = new byte[dataLen+2];
        raf.read(data1, 0, dataLen);
        System.out.println(new String(data1));
            
        // 把插入点后的内容保存起来
        raf.seek(dataLen);              // 将位置定位到插入点之后
        FileInputStream fis = new FileInputStream(new 
                                    BufferedOutputStream(temp));
        FileOutputStream fos = new FileOutputStream(new 
                                    BufferedOutputStream(temp));
        byte[] buffer = new byte[dataLen + 2];
        int len = -1;
        while ((len = raf.read(buffer)) != -1)
            fos.wirte(buffer, 0, len);
            
        raf.seek(dataLen);
        raf.write(", 亭台六七座".getBytes());
        // 插入完成后将缓冲的后半部分内容添加进来
        while ((len = fis.read(buffer)) != -1)
            raf.write(buffer, 0, len);
            
        raf.seek(0);  
        int fileLen = raf.length();
        byte[] data2 = new byte[fileLen + 2];
        raf.read(data2, 0, fileLen);
        
        System.out.println(new String(data2));
        
        输出:    烟村四五家......
                 烟村四五家, 亭台六七座......

三、总结:

  • File 类 是对文件和目录路径的 抽象,用户通过 File 来直接执行与文件或目录相关的操作,无需关心操作系统的差异。
  • RandomAccessFile 类 可以写入和读取文件,其最大的特点就是可以在任意位置读取文件(random access 的意思),是通过文件指针实现的。

正文完
 0