• 偶遇RandomAccessFile


    一、前言

      本来在研究NIO,别人举的栗子里面,看到一个RandomAccessFile类,之前没见过,就去看了一下,现将相关内容记录如下

    二、正文

      RandomAccessFile直接继承自Object,并且实现DataInput和DataOutput接口,它不属于InputStream和OutputStream类系的,并不是针对流的操作,它能在读取文件的时候前后移动,这个是和其他针对流操作的I/O类的本质区别。

      基本上,RandomAccessFile的工作方式是,把DataInputStream和DataOutputStream粘起来,再加上它自己的一些方法,比如定位用的getFilePointer( ),在文件里移动用的seek( ),以及判断文件大小的length( )。此外,它的构造函数还要一个表示以只读方式("r"),还是以读写方式("rw")打开文件的参数 (和C的fopen( )一模一样),它不支持只写文件。它支持对文件随机访问的读取和写入,即我们可以在指定的位置从文件读取/写入数据。

      平时,我们如果要往一个文件末尾追加一些数据,我们会将文件加载到内存,然后进行操作,但是如果文件本身非常大,比如好几G的量,那么普通的电脑承受不了,我们这时就可以使用RandomAccessFile,它无需将文件内容加载在内存,便可以在文件末尾追加内容。当然,有可能很多人会问,这个RandomAccessFile可以在文件指定位置插入数据吗?答案是:RandomAccessFile只能在指定位置修改数据,并不能插入数据(据我所知貌似没有哪个类支持在某个文件某个位置插入数据吧)。

      RandomAccessFile在读取等长数据的情况下也有优势。

      下面给出RandomAccessFile相关使用实例,先看下要操作的文件内容:

      

      

    //实例一,从指定位置读取文件
    package com.randomaccessfile.demo;
    
    import java.io.RandomAccessFile;
    
    /**
     * 
     * @author cyg
     * @date 2017-6-3 下午02:33:13
     * @description 随机读取文件的内容
     */
    public class Demo1 {
        public static void main(String[]args) throws Exception{
            //文件内容:hello world!
            RandomAccessFile raf = new RandomAccessFile("C:\Users\jackalc\Desktop\demo.txt", "r");
            System.out.println("在未指定位置之前,文件指针:"+raf.getFilePointer());
            raf.seek(6);//指定文件指针位置,从0开始
            System.out.println("在指定位置之后,文件指针:"+raf.getFilePointer());
            int readLength = 0;
            byte [] bytes = new byte[1024];
            while((readLength=raf.read(bytes))>0){
                System.out.println(new String(bytes,0,readLength));
            }
        }
    }
    
    //输出
    在未指定位置之前,文件指针:0
    在指定位置之后,文件指针:6
    world!
    //实例二,文件末尾追加内容
    package com.randomaccessfile.demo;
    
    import java.io.RandomAccessFile;
    
    /**
     * 
     * @author cyg
     * @date 2017-6-3 下午02:33:13
     * @description 文件末尾追加内容
     */
    public class Demo2 {
        public static void main(String[]args) throws Exception{
            //文件内容:hello world!
            RandomAccessFile raf = new RandomAccessFile("C:\Users\jackalc\Desktop\demo.txt", "rw");//读写方式打开
            raf.seek(raf.length());//将文件的指针移动到原先内容最后一个字节的后面
            raf.write("最末尾追加的内容".getBytes());
        }
    }

      实例二运行后,文件内容变更为:

      

     

    //实例三,在文件指定位置修改文件
    package com.randomaccessfile.demo;
    
    import java.io.RandomAccessFile;
    
    /**
     * 
     * @author cyg
     * @date 2017-6-3 下午02:33:13
     * @description 在文件指定位置修改文件
     */
    public class Demo3 {
        public static void main(String[]args) throws Exception{
            //文件内容:hello world!
            RandomAccessFile raf = new RandomAccessFile("C:\Users\jackalc\Desktop\demo.txt", "rw");//读写方式打开
            raf.seek(6);//"6"是“w”所在的位置
            raf.write("我现在在指定的位置修改内容,我会覆盖从指定位置开始,和我等长的文件内容!".getBytes());
        }
    }

      实例三运行之后,文件内容变更成这样:

      

      如果想要在文件指定位置插入数据,而不是修改数据,要怎么操作呢?RandomAccessFile并没有提供这个方法,对于这个需求,我们可以将指定位置后面的内容先存储到临时文件里面,然后等内容插入完,我们再将临时文件的内容插入到刚刚插入的内容后面,贴一下别人的代码(原文见“三、连接”处):

    //实例四,在文件指定位置插入内容
    package com.randomaccessfile.demo;
    
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.RandomAccessFile;
    
    /**
     * 
     * @author cyg
     * @date 2017-6-3 下午02:33:13
     * @description 在文件指定位置插入内容
     */
    public class Demo4 {
        public static void main(String[] args) {
            //文件内容:hello world!
            String path="C:\Users\jackalc\Desktop\demo.txt";         
            insert(path, 6, "这是我需要插入的内容,不覆盖原先的内容");  
        }  
        /** 
         * 实现向指定位置 
         * 插入数据 
         * @param fileName 文件名 
         * @param points 指针位置 
         * @param insertContent 插入内容 
         * **/  
        public static void insert(String fileName,long points,String insertContent){  
            try{  
            File tmp=File.createTempFile("tmp", null);  
            tmp.deleteOnExit();//在JVM退出时删除  
              
            RandomAccessFile raf=new RandomAccessFile(fileName, "rw");  
            //创建一个临时文件夹来保存插入点后的数据  
            FileOutputStream tmpOut=new FileOutputStream(tmp);  
            FileInputStream tmpIn=new FileInputStream(tmp);  
            raf.seek(points);  
            /**将插入点后的内容读入临时文件夹**/  
              
            byte [] buff=new byte[1024];  
            //用于保存临时读取的字节数  
            int hasRead=0;  
            //循环读取插入点后的内容  
            while((hasRead=raf.read(buff))>0){  
                // 将读取的数据写入临时文件中  
                tmpOut.write(buff, 0, hasRead);  
            }  
              
            //插入需要指定添加的数据  
            raf.seek(points);//返回原来的插入处  
            //追加需要追加的内容  
            raf.write(insertContent.getBytes());  
            //最后追加临时文件中的内容  
            while((hasRead=tmpIn.read(buff))>0){  
                raf.write(buff,0,hasRead);  
            }  
            }catch(Exception e){  
                e.printStackTrace();  
            }  
        }  
    }

      实例四运行完之后,文件内容如下:

    三、链接

    1、http://blog.csdn.net/czplplp_900725/article/details/37809579

    2、http://www.cnblogs.com/skywang12345/p/io_26.html

    3、http://baike.baidu.com/link?url=XqFXrey5USYJQ9kJVKufnL18QtobxJ6DRvYVfjUhXINC8Afctou3qKiN12ZPFSPUNLzyqMGa1ttl12zR7ZG-DA_hv7m3_MLmnSWNdYT6-re

    四、联系本人

      为方便没有博客园账号的读者交流,特意建立一个企鹅群(纯公益,非利益相关),读者如果有对博文不明之处,欢迎加群交流:261746360,小杜比亚-博客园

  • 相关阅读:
    0414结对 复利
    0619-学习进度条
    测试
    冲刺一总结
    实验四主存空间的分配和回收
    0622-软件工程学期总结
    学术诚信与职业道德有感
    《构建之法》第8、9、10章
    0512 操作系统进程调度实验
    构建之法 第6~7章读后感和对Scrum的理解
  • 原文地址:https://www.cnblogs.com/xdouby/p/6937434.html
Copyright © 2020-2023  润新知