zoukankan      html  css  js  c++  java
  • Java IO(二)——RandomAccessFile

    一、RandomAccessFile

    RandomAccessFile类可以说是Java语言中功能最为丰富的文件访问类,它提供了众多的文件访问方法。RandomAccessFile类支持"随机访问"方式,可以跳转到文件的任意位置处读写数据。要访问一个文件的时候,不想把文件从头读到尾,而是希望像访问一个数据库一样地访问一个文本文件,使用RandomAccessFile类是最佳选择。

    RandomAccessFile对象类中有个位置指示器,指向当前读写处的位置,当读写n个字节后,文件指示器将指向这n个字节后的下一个字节处。刚打开文件时,文件指示器指向文件的开头处,可以移动文件指示器到新的位置,随后的读写将从新的位置开始。

    RandomAccessFile类在文件随机(相对于顺序)读取时有很大的优势,但该类仅限于操作文件,不能访问其他得IO设备,如网络、内存映像等

    二、RandomAccessFile构造方法

    RandomAccessFile类为用户提供了两种构造方法:

    1、RandomAccessFile(File file, String mode)

    2、RandomAccessFile(String name, String mode)

    其实第二种构造方法也是new一个File出来再调用第一种构造方法,建议使用第一种构造方法,因为第一篇文章就说了File是IO的基础,有一个File不仅仅可以通过RandomAccessFile对文件进行操作,也可以通过File对象对文件进行操作。至于mode,Java给开发者提供了四种mode:

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

    注意第二点"rw"模式,对rw模式的解释意味着Java并不强求指定的路径下一定存在某个文件,假如文件不存在,会自动创建。

    三、RandomAccessFile中的方法

    RandomAccessFile中有如下一些常用方法:

    方    法 作    用
    void close() 重要,关闭此随机访问文件流并释放与该流关联的所有系统资源
    FileChannel getChannel() 返回与此文件关联的唯一FileChannel对象,NIO用到
    long getFilePointer() 返回此文件中的当前偏移量
    long length() 返回此文件的长度
    int read() 从此文件中读取一个数据字节
    int read(byte[] b) 将最多b.length个数据字节从此文件读入byte数组,返回读入的总字节数,如果由于已经达到文件末尾而不再有数据,则返回-1。在至少一个输入字节可用前,此方法一直阻塞
    int read(byte[] b, int off, int len) 将最多len个数据字节从此文件的指定初始偏移量off读入byte数组
    boolean readBoolean() 从此文件读取一个boolean,其余readByte()、readChar()、readDouble()等类似
    String readLine() 从此文件读取文本的下一行
    void seek(long pos) 重要,设置到此文件开头测量到的文件指针偏移量,在该位置发生下一个读取或写入操作
    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写入该文件,其余writeByte(int v)、writeBytes(String s)、writeChar(int v)等都类似

    三、RandomAccessFile使用实例

    先定义一个实体类:

    package com.demo.entity;
    
    public class Employee {
    
        private String name;
        private int age;
        private final static int LEN = 8;
    
        public Employee() {
    
        }
    
        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 String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public int getAge() {
            return age;
        }
    
        public void setAge(int age) {
            this.age = age;
        }
    
    }

    第一部分,写文件,该文件在路径下并没有,所以Java会自动帮我们创建:

    /**
     * 写文件
     */
    @Test
    public void writeFile() throws IOException{
        Employee e1 = new Employee("zhangsan", 23);
        Employee e2 = new Employee("lisi", 24);
        Employee e3 = new Employee("wangwu", 25);
        
        RandomAccessFile raf0 = new RandomAccessFile("D:/Files/employee.txt", "rw");
        raf0.writeBytes(e1.getName());
        raf0.writeInt(e1.getAge());
        raf0.writeBytes(e2.getName());
        raf0.writeInt(e2.getAge());
        raf0.writeBytes(e3.getName());
        raf0.writeInt(e3.getAge());
        raf0.close();
    }

    文件创建好了,D盘下的Files文件夹也有该文件了,所以读取一下,这里使用了一些小技巧来演示seek方法和skipBytes方法:

    /**
     * 读文件
     */
    @Test
    public void ReadFile() throws IOException{
        RandomAccessFile raf1 = new RandomAccessFile("D:/Files/employee.txt", "r");
        int len = 8;
        raf1.skipBytes(12); // 跳过第一个员工的信息,其姓名8字节,年龄4字节
        System.out.println("第二个员工的信息:");
        String str = "";
        for (int i = 0; i < len; i++)
        {
            str = str + (char)raf1.readByte();
        }
        System.out.println("name:" + str);
        System.out.println("age:" + raf1.readInt());
        System.out.println("第一个员工的信息:");
        raf1.seek(0);
        str = "";
        for (int i = 0; i < len; i++)
        {
            str = str + (char)raf1.readByte();
        }
        System.out.println("name:" + str);
        System.out.println("age:" + raf1.readInt());
        System.out.println("第三个员工的信息:");
        raf1.skipBytes(12); // 跳过第二个员工的信息
        str = "";
        for (int i = 0; i < len; i++)
        {
            str = str + (char)raf1.readByte();
        }
        System.out.println("name:" + str.trim());
        System.out.println("age:" + raf1.readInt());
        raf1.close();
    }

    看一下运行结果:

    第二个员工的信息:
    name:lisi
    age:24
    第一个员工的信息:
    name:zhangsan
    age:23
    第三个员工的信息:
    name:wangwu
    age:25

    可能有人奇怪,"zhangsan"加上一个int跳过12个字节可以理解,但是"lisi"、"wangwu"为什么加上int要跳过12个字节呢?明明"lisi"只有4个字节,"wangwu"只有6个字节啊。这个就涉及到一个"字节对齐"的问题了,有兴趣的可以了解一下。另外,再说一下,RandomAccessFile使用完一定要及时close()。

  • 相关阅读:
    SQL Server 阻止了对组件 'Ole Automation Procedures' 的 过程'sys.sp_OACreate' 的访问
    谷歌浏览器扩展程序manifest.json参数详解
    获取天气api
    UVA 10385 Duathlon
    UVA 10668 Expanding Rods
    UVALIVE 3891 The Teacher's Side of Math
    UVA 11149 Power of Matrix
    UVA 10655 Contemplation! Algebra
    UVA 11210 Chinese Mahjong
    UVA 11384 Help is needed for Dexter
  • 原文地址:https://www.cnblogs.com/xiaoxi/p/6483390.html
Copyright © 2011-2022 走看看