RandomAccessFile

  • 功能
  • 构造函数
  • 特殊方法


功能

想比较之前的流要么读要么写,RandomAccessFile提供了读写操作RandomAccessFile声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了Datalnput、DataOutput两个接口
看源码

public class RandomAccessFile implements DataOutput, DataInput, Closeable

构造函数

public RandomAccessFile(String name, String mode)
public RandomAccessFile(File file, String mode)

3.如果RandomAccessFile作为输出流时,写出到的文件如果不存在,则在执行过程中自动创建 如果写出到的文件存在,则会对原有文件内容进行覆盖。(默认情况下,从头覆盖)

public static void main(String[] args) {
        RandomAccessFile raf1 = null;
        RandomAccessFile raf2 = null;
        try {
            raf1 = new RandomAccessFile(new File("D:\\IO\\hao.jpg"), "r");
            raf2 = new RandomAccessFile(new File("D:\\IO\\a.jpg"), "rw");
            byte[] buffer = new byte[1024];
            int len;
            while ((len = raf1.read(buffer)) != -1) {
                raf2.write(buffer, 0, len);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (raf1 != null) {
                try {
                    raf1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (raf2 != null) {
                try {
                    raf2.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

RandomAccessFile 写空的大文件 randomaccessfile raf2=new_临时文件

主要是第二个参数:指定访问模式,有哦4种模式
r:以只读的模式打开,如果调用write方法将会抛出IO异常
rw:以读和写的模式打开
rws:以读和写的模式打开,要求对”文件的内容“和”元数据“的每个更新都同步到存储设备
rwd:以读和写的模式打开,要求对”文件的内容“的每个更新都同步到存储设备

特殊方法

long getFilePointer() //返回文件记录中指针的当前位置
void seek(long pos) //将文件记录移动到指定的pos文件

练习1:

@Test
    public void test2() throws Exception {
        RandomAccessFile raf1 = new RandomAccessFile("hello1.txt", "rw");
        raf1.seek(3);//将指针跳到角标为3的位置
        raf1.write("aaa".getBytes());//xyzaaa
        System.out.println(raf1.getFilePointer());//6
        raf1.close();

    }

练习2:

使用RandomAccessFile实现数据的插入效果

  • xyz…fggggrtb …为要插入的位置
    例如:插入aaa
    结果为xyzaaafggggrtb
@Test
    public void  Test3 () throws Exception {
     RandomAccessFile raf3 = new RandomAccessFile("hello.txt", "rw");
     raf3.seek(3);//将指针跳到角标为3的位置从1开始
     
     //StringBuilder替代字符串拼接,长度大于16了要扩容
     //为了避免扩容,我们直接使用要拼接字符串长度
     StringBuilder  builder = new StringBuilder((int)new File("hello.txt").length()); //保存指针3后面的所有数据到   StringBuilder中
     //StringBuilder替代字符串拼接,长度大于16了要扩容
     //为了避免扩容,我们直接使用要拼接字符串长度
     byte[] buffer = new byte[20];
     int len;
     while ((len = raf3.read(buffer))!=-1){
         builder.append(new String(buffer,0,len));
     }
     //跳回
     raf3.seek(3);
     raf3.write("xyz".getBytes());
     //将StringBuilder中的数据写入到文件中
     raf3.write(builder.toString().getBytes());

 }

RandomAccessFile 写空的大文件 randomaccessfile raf2=new_临时文件_02


来看看另一种插入数据的方法

/**
 *  完成数据内容的插入
 * @param path  文件路径
 * @param index  指定数据插入位置
 * @param cont  插入的内容
 */
public class Test4 {
    public static void main(String[] args) {
        insertContent("D:\\IO\\b.txt",3,"123");

    }

/*
* 1、校验参数的合法性
2、将指针移动到插入的位置
3、通过流读取出来写到磁盘文件上(开辟读和写的流)
4、将指针重新指定到插入位置
5、将写入的内容write写入
6、将后续内存重新写入该文件
*
*
* */
public static void insertContent(String path,int index,String cont)  {
    File file = new File(path);
    if(!file.exists()){
        return;
    }
    if(index<0){
        return;
    }
    FileInputStream tmppis = null;
    FileOutputStream tmpos1 = null;
    RandomAccessFile randomAccessFile =null;
    File tmpfile = new File(file.getParent()+file.separator+"temp.txt");
    try {
        //写入临时文件
        tmpos1 = new FileOutputStream(tmpfile);
        //读取临时文件
         tmppis = new FileInputStream(tmpfile);
        //打开目标文件
         randomAccessFile = new RandomAccessFile(file, "rw");
        //指定要插入文件位置
        randomAccessFile.seek(index);
        //把该位置文件读取出来
        byte[] bytes = new byte[100];
        int len;
        while ((len= randomAccessFile.read(bytes))!=-1){
            //写入临时文件
            tmpos1.write(bytes,0,len);
        }
        tmpos1.flush();
        //将指针移动到指定位置
        randomAccessFile.seek(index);
        randomAccessFile.write(cont.getBytes());
        //将临时文件内容重写写入原文件
        while ((len=tmppis.read(bytes))!=-1){
            randomAccessFile.write(bytes,0,len);
        }

    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }finally {
        if (tmppis != null){
            try {
                tmppis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if(tmpos1 !=null){
                try {
                    tmpos1.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }if(randomAccessFile != null){
            try {
                randomAccessFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
}

new String源码:
功能:把byte类型的数组,转码为String

public String(byte bytes[], int offset, int length) {
        checkBounds(bytes, offset, length);
        this.value = StringCoding.decode(bytes, offset, length);
    }

String 的getBytes源码:
得到一个操作系统默认的编码格式的字节数组。
这表示在不同的操作系统下,返回的东西不一样
?

public byte[] getBytes() {
        return StringCoding.encode(value, 0, value.length);
    }