Administrator
发布于 2024-07-01 / 7 阅读
0
0

RandomAccessFile

理论

Java除了File类之外,还提供了专门处理文件的类,即RandomAccessFile(随机访问文件)类。

该类是Java语言中功能最为丰富的文件访问类,它提供了众多的文件访问方法。RandomAccessFile类支持“随机访问”方式,这里“随机”是指可以跳转到文件的任意位置处读写数据。在访问一个文件的时候,不必把文件从头读到尾,而是希望像访问一个数据库一样“随心所欲”地访问一个文件的某个部分,这时使用RandomAccessFile类就是最佳选择。

RandomAccessFile对象类有个位置指示器,指向当前读写处的位置,当前读写n个字节后,文件指示器将指向这n个字节后面的下一个字节处。

刚打开文件时,文件指示器指向文件的开头处,可以移动文件指示器到新的位置,随后的读写操作将从新的位置开始。

RandomAccessFile类在数据等长记录格式文件的随机(相对顺序而言)读取时有很大的优势,但该类仅限于操作文件,不能访问其他的I/O设备,如网络、内存映像等。

RandomAccessFile类的构造方法如下所示:

//创建随机存储文件流,文件属性由参数File对象指定
RandomAccessFile(File file ,  String mode)

//创建随机存储文件流,文件名由参数name指定
RandomAccessFile(String name ,  String mode)

这两个构造方法均涉及到一个String类型的参数mode,它决定随机存储文件流的操作模式,其中mode值及对应的含义如下:

  • “r”:以只读的方式打开,调用该对象的任何write(写)方法都会导致IOException异常
  • “rw”:以读、写方式打开,支持文件的读取或写入。若文件不存在,则创建之。
  • “rws”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。这里的“s”表示synchronous(同步)的意思
  • “rwd”:以读、写方式打开,与“rw”不同的是,还要对文件内容的每次更新都同步更新到潜在的存储设备中去。使用“rwd”模式仅要求将文件的内容更新到存储设备中,而使用“rws”模式除了更新文件的内容,还要更新文件的元数据(metadata),因此至少要求1次低级别的I/O操作
import java.io.RandomAccessFile;
import java.nio.charset.StandardCharsets;
public class RandomFileTest {
    private static final String filePath = "C:\\Users\\NineSun\\Desktop\\employee.txt";

    public static void main(String[] args) throws Exception {
        Employee e1 = new Employee("zhangsan", 23);
        Employee e2 = new Employee("lisi", 24);
        Employee e3 = new Employee("wangwu", 25);
        RandomAccessFile ra = new RandomAccessFile(filePath, "rw");
        ra.write(e1.name.getBytes(StandardCharsets.UTF_8));//防止写入文件乱码
        ra.writeInt(e1.age);
        ra.write(e2.name.getBytes());
        ra.writeInt(e2.age);
        ra.write(e3.name.getBytes());
        ra.writeInt(e3.age);
        ra.close();
        RandomAccessFile raf = new RandomAccessFile(filePath, "r");
        int len = 8;
        raf.skipBytes(12);//跳过第一个员工的信息,其姓名8字节,年龄4字节
        System.out.println("第二个员工信息:");
        String str = "";
        for (int i = 0; i < len; i++) {
            str = str + (char) raf.readByte();
        }
        System.out.println("name:" + str);
        System.out.println("age:" + raf.readInt());
        System.out.println("第一个员工信息:");
        raf.seek(0);//将文件指针移动到文件开始位置
        str = "";
        for (int i = 0; i < len; i++) {
            str = str + (char) raf.readByte();
        }
        System.out.println("name:" + str);
        System.out.println("age:" + raf.readInt());
        System.out.println("第三个员工信息:");
        raf.skipBytes(12);//跳过第二个员工的信息
        str = "";
        for (int i = 0; i < len; i++) {
            str = str + (char) raf.readByte();
        }
        System.out.println("name:" + str);
        System.out.println("age:" + raf.readInt());
        raf.close();
    }
}

class Employee {
    String name;
    int age;
    final static int LEN = 8;

    public Employee(String name, int age) {
        if (name.length() > LEN) {
            name = name.substring(0, 8);
        } else {
            while (name.length() < LEN) {
                name = name + "\u0000";
            }
            this.name = name;
            this.age = age;
        }
    }

样例


public void writeByteDataToFile(byte[] fileData, File tempFile,FileUploadMetadataBO fileUploadMetadata) {
        RandomAccessFile raf;

        try {
            raf = new RandomAccessFile(tempFile, "rw");
            //这个必须与前端设定的值一致
            long chunkSize = Objects.isNull(fileUploadMetadata.getChunkSize()) ? uploadProperties.getDefaultChunkSize() * 1024 * 1024
                    : fileUploadMetadata.getChunkSize();
             // 这里的getChunk(),是从0开始的       
            long offset = chunkSize * fileUploadMetadata.getChunk();
            //定位到该分片的偏移量
            raf.seek(offset);
            //写入该分片数据
            raf.write(fileData);
            // TODO 检查

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        }
    }

评论