RandomAccessFile java IO

Posted hello4world

tags:

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

1.写入字节

/**
 * java.io.RandomAccessFile
 * RAF是专门用来读写文件数据的API,其基于指针对文件任意位置进行读写.
 */
public class RafDemo1 {
    public static void main(String[] args) throws IOException {
        /*
         * 对当前目录下的raf.dat文件读写数据
         */
        RandomAccessFile raf = new RandomAccessFile("./raf.dat","rw");
        /*
         * void write(int d)
         * 向文件中写入1个字节,写入的是给定的int值
         * 所对应2进制的"低八位"
         *                            vvvvvvvv
         * 00000000 00000000 00000000 00000001
         */
        raf.write(1);        
        System.out.println("写出完毕!");        
        raf.close();        
    }
}

2.读取字节

/**
 * 从文件中读取字节
 */
public class RafDemo2 {
    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("raf.dat","r");
        /*
         * int read()
         * 从文件中读取1个字节,并以int形式
         * 返回.若返回值为-1则表示文件末尾
         * 00000000 00000000 00000000 11111111
         */
        int d = raf.read();
        System.out.println(d);        
        d = raf.read();
        System.out.println(d);        
        System.out.println("读取完毕!");
        raf.close();
    }
}

3.读写基本类型数据以及RAF基于指针的操作

/**
 * 读写基本类型数据以及RAF基于指针的操作
 */
public class RafDemo3 {
    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("raf.dat","rw");
        /*
         * 获取RAF指针位置,创建后从0开始(文件第
         * 一个字节位置)
         */
        long pos = raf.getFilePointer();
        System.out.println("pos:"+pos);
        /*
         * 向文件中写入一个int最大值
         *                            vvvvvvvv
         * 01111111 11111111 11111111 11111111  
         * imax>>>24
         * 00000000 00000000 00000000 01111111                          
         */
        int imax = Integer.MAX_VALUE;
        System.out.println(imax);    
        raf.write(imax>>>24);
        System.out.println("pos:"+raf.getFilePointer());
        raf.write(imax>>>16);
        raf.write(imax>>>8);
        raf.write(imax);
        System.out.println("pos:"+raf.getFilePointer());
        /*
         * void writeInt(int d)
         * 将给定的int值对应的4字节一次性写出
         * 等同上面四句操作
         */
        raf.writeInt(imax);
        System.out.println("pos:"+raf.getFilePointer());
        raf.writeLong(123L);
        System.out.println("pos:"+raf.getFilePointer());
        raf.writeDouble(123.123);
        System.out.println("pos:"+raf.getFilePointer());
        System.out.println("写出完毕!");    
        /*
         * void seek(long pos)
         * 移动指针到指定位置
         */
        raf.seek(0);
        System.out.println("pos:"+raf.getFilePointer());
        /*
         * int readInt()
         * 连续读取4个字节并返回该int值,若连续读取
         * 4个字节的过程中发现读取到了文件末尾,此时
         * 会直接抛出异常EOFException
         * EOF(end of file)文件末尾
         */
        int d = raf.readInt();
        System.out.println(d);
        System.out.println("pos:"+raf.getFilePointer());    
        //读取long值
        //1移动指针到long的所在位置
        raf.seek(8);
        //2读取long的8字节还原long值
        long lon = raf.readLong();
        System.out.println(lon);
        System.out.println("pos:"+raf.getFilePointer());        
        double dou = raf.readDouble();
        System.out.println(dou);
        System.out.println("pos:"+raf.getFilePointer());        
        /*
         * 将第二个int值内容改为int最小值
         */
        //1移动指针到第二个int值的开始位置
        raf.seek(4);
        //2重写写入新的int值来覆盖原内容
        raf.writeInt(Integer.MIN_VALUE);
        System.out.println("pos:"+raf.getFilePointer());        
        raf.seek(4);
        d = raf.readInt();
        System.out.println(d);        
        raf.close();        
    }
}

4.用RAF复制文件(单字节,很慢)

/**
 * 复制文件
 */
public class CopyDemo {
    public static void main(String[] args) throws IOException {
        RandomAccessFile src = new RandomAccessFile("./movie.mp4","r");        
        RandomAccessFile desc = new RandomAccessFile("./movie_cp.mp4","rw");        
        int d = -1;//用于保存每次读取到的字节
        long start = System.currentTimeMillis();
        while((d = src.read())!=-1) {
            desc.write(d);
        };
        long end = System.currentTimeMillis();
        System.out.println("复制完毕!耗时:"+(end-start)+"ms");
        src.close();
        desc.close();
    }
}

5.用RAF复制文件(块读,速度快)

/**
 * 通过提高每次读写的数据量,减少实际读写的次数可以提高读写效率. 
 * 单字节读写是随机读写,效率差
 * 块读写是一组一组字节的读写,效率高
 */
public class CopyDemo2 {
    public static void main(String[] args) throws IOException {
        RandomAccessFile src = new RandomAccessFile("movie.mp4","r");
        RandomAccessFile desc = new RandomAccessFile("movie_cp.mp4","rw");    
        /*
         * int read(byte[] data)
         * 一次性从文件中读取给定数组总长度的字节量,并将读取到的数据存入到该数组
         * 中,返回值为实际读取到的字节量.若返回值为-1,则表示文件末尾(本次没有
         * 读取到任何数据)
 
         * void write(byte[] data)
         * 一次性将给定字节数组中所有字节写入文件
         * 
         * void write(byte[] data,int s,int len)
         * 将给定字节数组从下标s处开始的连续len个字节一次性写入文件
         */
        //10K
        byte[] data = new byte[1024*10];
        int len = -1;//每次实际读取到的字节数        
        long start = System.currentTimeMillis();
        while((len = src.read(data))!=-1) {
            desc.write(data,0,len);
        }
        long end = System.currentTimeMillis();
        System.out.println("复制完毕!耗时"+(end-start)+"ms");
        src.close();
        desc.close();
    }
}

6.读取文本数据

/**
 * 读取文本数据
 */
public class ReadStringDemo {
    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("raf.txt","r");    
        byte[] data = new byte[(int)raf.length()];
        raf.read(data);        
        String str = new String(data,"UTF-8");
        System.out.println(str);        
        raf.close();
    }
}

7.写入字符串

/**
 * 使用RAF向文件中写入字符串 
 */
public class WriteStringDemo {
    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("raf.txt","rw");
        String line = "夜空中最亮的星";
        /*
         * String提供了转换为字节的方法:
         * byte[] getBytes()
         * 将当前字符串按照系统默认字符集转换为一组字节
         * 
         * byte[] getBytes(String csn)
         * 重载的getBytes方法要求我们传入一个
         * 字符串参数表示字符集的名称,该名称
         * 不区分大小写,作用是将当前字符串按照
         * 给定的字符集转换为一组字节,推荐用
         * 这种方式,不要按照系统默认字符集操作. 
         */
        byte[] data = line.getBytes("UTF-8");        
        raf.write(data);        
        raf.write(",能否听清,".getBytes("UTF-8"));        
        System.out.println("写出完毕!");
        raf.close();
    }
}

8.RAF简单应用

/**
 * 用户注册
 * 程序启动后,要求用户输入注册信息:
 * 用户名,密码,昵称,年龄
 * 其中除了年龄是int值外,其余三个是String.
 * 然后将该信息写入user.dat文件中保存.
 * 
 * 每条记录固定占用100字节.
 * 其中用户名,密码,昵称为字符串,各占用32字节.
 * 年龄为int值固定的4字节.
 */
public class RegDemo {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("欢迎注册");        
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();        
        System.out.println("请输入密码:");
        String password = scanner.nextLine();        
        System.out.println("请输入昵称:");
        String nickname = scanner.nextLine();        
        System.out.println("请输入年龄:");
        int age = Integer.parseInt(scanner.nextLine());        
        System.out.println(username+","+password+","+nickname+","+age);    
        RandomAccessFile raf = new RandomAccessFile("user.dat","rw");
        //首先将指针移动到文件末尾,以便追加新记录
        raf.seek(raf.length());        
        //写入用户名
        byte[] data = username.getBytes("UTF-8");
        //扩容数组到32字节
        data = Arrays.copyOf(data, 32);
        raf.write(data);        
        //写密码
        data = password.getBytes("UTF-8");
        data = Arrays.copyOf(data, 32);
        raf.write(data);        
        //写昵称
        data = nickname.getBytes("UTF-8");
        data = Arrays.copyOf(data, 32);
        raf.write(data);        
        //写年龄
        raf.writeInt(age);        
        System.out.println("pos:"+raf.getFilePointer());    
        System.out.println("注册完毕!");
        raf.close();
    }
}
/**
 * 将user.dat文件中的用户信息显示到控制台
 */
public class ShowAllUserDemo {
    public static void main(String[] args) throws IOException {
        RandomAccessFile raf = new RandomAccessFile("user.dat","r");        
        for(int i=0;i<raf.length()/100;i++) {
            byte[] data = new byte[32];
            raf.read(data);
            String username = new String(data,"UTF-8").trim();            
            raf.read(data);
            String password = new String(data,"UTF-8").trim();            
            raf.read(data);
            String nickname = new String(data,"UTF-8").trim();            
            int age = raf.readInt();            
            System.out.println(username+","+password+","+nickname+","+age);
            System.out.println("pos:"+raf.getFilePointer());
        }        
        raf.close();
    }
}
/**
 * 完成修改昵称操作
 * 
 * 程序启动后要求输入用户名和新的昵称.然后
 * 修改user.dat文件中该用户的昵称.
 * 若输入的用户名在user.dat文件中不存在则输出
 * 提示信息:该用户不存在!
 */
public class UpdateDemo {
    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        System.out.println("请输入用户名:");
        String username = scanner.nextLine();
        System.out.println("请输入新的昵称:");
        String nickname = scanner.nextLine();        
        RandomAccessFile raf = new RandomAccessFile("user.dat","rw");        
        boolean updated = false;//是否修改过信息
        for(int i=0;i<raf.length()/100;i++) {
            //移动到每条记录的开始位置
            raf.seek(i*100);
            //读取用户名
            byte[] data = new byte[32];
            raf.read(data);
            String name = new String(data,"UTF-8").trim();
            if(name.equals(username)) {
                //移动指针到昵称位置
                raf.seek(i*100+64);
                data = nickname.getBytes("UTF-8");
                data = Arrays.copyOf(data, 32);
                raf.write(data);
                System.out.println("修改完毕!");
                updated = true;
                break;
            }
        }
        if(!updated) {
            System.out.println("该用户不存在!");
        }
        raf.close();
    }
}

以上是关于RandomAccessFile java IO的主要内容,如果未能解决你的问题,请参考以下文章

RandomAccessFile java IO

Java IO流 之 RandomAccessFile 多线程下载

java基础之 IO 流(RandomAccessFile类)

Java IO2:RandomAccessFile

Java IO流RandomAccessFile类的使用

Java.io.RandomAccessFile