详解 随机访问流

Posted codderyouzg

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了详解 随机访问流相关的知识,希望对你有一定的参考价值。

(请观看本人博文——《详解 I/O流》)

RandomAccessFile 类

(随机访问流)

概述:

RandomAccessFile 类 的实例支持对随机访问文件的读取和写入
随机访问文件的行为类似存储在文件系统中的一个大型 byte 数组。
存在指向该隐含数组的光标或索引,称为文件指针;
输入操作从文件指针开始读取字节,并随着对字节的读取而前移此文件指针。如果随机访问文件以读取/写入模式创建,则输出操作也可用;
输出操作从文件指针开始写入字节,并随着对字节的写入而前移此文件指针。写入隐含数组的当前末尾之后的输出操作导致该数组扩展。
该文件指针可以通过 getFilePointer 方法读取,并通过 seek 方法设置。
通常,如果此类中的所有读取例程在读取所需数量的字节之前已到达文件末尾,则抛出 EOFException(是一种 IOException)。
如果由于某些原因无法读取任何字节,而不是在读取所需数量的字节之前已到达文件末尾,则抛出 IOException,而不是 EOFException。
需要特别指出的是,如果流已被关闭,则可能抛出 IOException

相信好多通信跟我一样,看了上面那么多文字,都会有一时间读不下去的感觉。那么,本人现在来总结下 这个类的特点

特点:

特点

  1. 能读能写;
  2. 此类 不属于流,是Object类的子类。但它融合了InputStream和OutputStream的功能;
  3. 支持对随机访问文件的读取和写入;
  4. 我们可以通过getFilePointer()方法获取文件指针,并且可以通过seek()方法设置文件指针
  5. 此流可以被应用于“断点续传”。

现在,本人来展示下这个类的构造方法

构造方法

  • RandomAccessFile(File file, String mode)
    创建从中读取和向其中写入(可选)的随机访问文件流,该文件由 File 参数指定
  • RandomAccessFile(String name, String mode)
    创建从中读取和向其中写入(可选)的随机访问文件流,该文件具有指定名称

本人现在对上述的mode参数做下解释:

参数 mode

  • "r" :
    只读方式打开。
    调用结果对象的任何 write() 方法都将导致抛出 IOException
  • "rw":
    打开以便读取和写入
    如果该文件尚不存在,则尝试创建该文件
  • "rws":
    打开以便读取和写入
    对于 "rw",还要求对 文件内容 或 元数据 的每个更新都同步写入到底层存储设备
  • "rwd":
    打开以便 读取和写入
    对于 "rw",还要求对 文件内容 的每个更新都同步写入到底层存储设备

现在,本人来展示下这个类的常用API

常用API

  • void close()
    关闭此随机访问文件流并释放与该流关联的所有系统资源
  • FileChannel getChannel()
    返回与此文件关联的唯一 FileChannel 对象
  • FileDescriptor getFD()
    返回与此流关联的不透明文件描述符对象
  • long getFilePointer()
    返回此文件中的当前偏移量
  • long length()
    返回此文件的长度
  • int read()
    从此文件中读取一个数据字节
  • int read(byte[] b)
    将最多 b.length 个数据字节从此文件读入 byte 数组
  • int read(byte[] b, int off, int len)
    将最多 len 个数据字节从此文件读入 byte 数组
  • boolean readBoolean()
    从此文件读取一个 boolean
  • byte readByte()
    从此文件读取一个有符号的八位值
  • char readChar()
    从此文件读取一个字符
  • double readDouble()
    从此文件读取一个 double
  • float readFloat()
    从此文件读取一个 float
  • void readFully(byte[] b)
    将 b.length 个字节从此文件读入 byte 数组,并从当前文件指针开始
  • void readFully(byte[] b, int off, int len)
    将正好 len 个字节从此文件读入 byte 数组,并从当前文件指针开始
  • int readInt()
    从此文件读取一个有符号的 32 位整数。
  • String readLine()
    从此文件读取文本的下一行
  • long readLong()
    从此文件读取一个有符号的 64 位整数
  • short readShort()
    从此文件读取一个有符号的 16 位数
  • int readUnsignedByte()
    从此文件读取一个无符号的八位数
  • int readUnsignedShort()
    从此文件读取一个无符号的 16 位数
  • String readUTF()
    从此文件读取一个字符串
  • void seek(long pos)
    设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作
  • void setLength(long newLength)
    设置此文件的长度
  • int skipBytes(int n)
    尝试跳过输入的 n 个字节以丢弃跳过的字节
  • void write(byte[] b)
    将 b.length 个字节从指定 byte 数组写入到此文件,并从当前文件指针开始
  • void write(byte[] b, int off, int len)
    将 len 个字节从指定 byte 数组写入到此文件,并从偏移量 off 处开始
  • void write(int b)
    向此文件写入指定的字节
  • void writeBoolean(boolean v)
    按单字节值将 boolean 写入该文件
  • void writeByte(int v)
    按单字节值将 byte 写入该文件
  • void writeBytes(String s)
    按字节序列将该字符串写入该文件
  • void writeChar(int v)
    按双字节值将 char 写入该文件,先写高字节
  • void writeChars(String s)
    按字符序列将一个字符串写入该文件
  • void writeDouble(double v)
    使用 Double 类中的 doubleToLongBits 方法将双精度参数转换为一个 long,然后按八字节数量将该 long 值写入该文件,先定高字节
  • void writeFloat(float v)
    使用 Float 类中的 floatToIntBits 方法将浮点参数转换为一个 int,然后按四字节数量将该 int 值写入该文件,先写高字节
  • void writeInt(int v)
    按四个字节将 int 写入该文件,先写高字节
  • void writeLong(long v)
    按八个字节将 long 写入该文件,先写高字节
  • void writeShort(int v)
    按两个字节将 short 写入该文件,先写高字节
  • void writeUTF(String str)
    首先,把两个字节从文件的当前文件指针写入到此文件,然后再录入字符串的相应字节信息

那么,现在,本人来通过一个例子展示下这个类的用法:

本人来展示下利用这个流来对一个mp4文件的复制:

package edu.youzg.about_io.about_file.core.Test;

import java.io.*;

public class Test {

    public static void main(String[] args) throws IOException{
        boolean end = false;
        String sourceFile = "G:\\Java\\plantsVSzombies.mp4";
        String targetFile = "copyFile.mp4";

        while (!end) {
            end = copyFile(sourceFile, targetFile);
        }
    }

    public static boolean copyFile(String sourceFile, String targetFile) throws IOException{
        RandomAccessFile reader = new RandomAccessFile(sourceFile, "rw");
        File file = new File(targetFile);
        boolean isExists = file.exists();
        RandomAccessFile writer = new RandomAccessFile(file, "rw");

        if(isExists){
            String s = new BufferedReader(new FileReader("temPos.txt")).readLine();
            int offset = Integer.parseInt(s);
            reader.seek(offset);
            writer.seek(offset);
        }else{
            reader.seek(0);
            writer.seek(0);
        }

        try {
            int len = 0;
            byte[] bytes = new byte[1024];
            int index = 1;
            while ((len = reader.read(bytes)) != -1) {
                writer.write(bytes,0,len);
            }
        }catch (Exception e){
            //一旦遇到异常,记录当前指针的位置
            long filePointer = reader.getFilePointer();
            System.out.println(filePointer);
            PrintWriter printWriter = new PrintWriter("temPos.txt");
            printWriter.println(filePointer);
            printWriter.flush();

            return false;
        }

        //释放资源
        reader.close();
        writer.close();

        return true;
    }

}

那么,本人先来展示下源文件的信息:
技术图片

本人再来展示下生成的文件的信息:
技术图片

通过上图,可以发现本人完成了文件的复制!
其实,上面的例子就是“断点续传”的一个基本模型。

(本人 I/O流总集篇 博文链接:https:////www.cnblogs.com/codderYouzg/p/12418404.html

以上是关于详解 随机访问流的主要内容,如果未能解决你的问题,请参考以下文章

IO---随机访问文件流

java 21 - 12 随机访问流(不属于IO流)

《七》随机访问文件流

Java基础——IO流4_随机访问文件流

黑马程序员——————> 随机访问流

随机访问 gzip 流