添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一、RandomAccessFile简介

RandomAccessFile 既可以读取文件内容,也可以向文件输出数据。同时,RandomAccessFile 支持“随机访问”的方式,程序快可以直接跳转到文件的任意地方来读写数据。

由于RandomAccessFile可以自由访问文件的任意位置, 所以如果需要访问文件的部分内容,而不是把文件从头读到尾,使用 RandomAccessFile 将是更好的选择。

与OutputStream、Writer等输出流不同的是,RandomAccessFile允许自由定义文件记录指针,RandomAccessFile可以不从开始的地方开始输出,因此RandomAccessFile可以向已存在的文件后追加内容。 如果程序需要向已存在的文件后追加内容,则应该使用RandomAccessFile。

RandomAccessFile的方法虽然多,但它有一个最大的局限,就是只能读写文件,不能读写其他IO节点。

RandomAccessFile的一个重要使用场景就是网络请求中的 多线程下载  及  断点续传。

2.RandomAccessFile的重要方法

RandomAccessFile  既可以读文件,也可以写文件,所以类似于InputStream的read()方法,以及类似于OutputStream的write()方法,RandomAccessFile都具备。除此之外,RandomAccessFile具备两个特有的方法,来支持其随机访问的特性。

RandomAccessFile对象包含了一个记录指针,用以标识当前读写处的位置,当程序新创建一个RandomAccessFile对象时,该对象的文件指针记录位于文件头(也就是0处),当读/写了n个字节后,文件记录指针将会后移n个字节。除此之外,RandomAccessFile还可以自由移动该记录指针。下面就是RandomAccessFile具有的两个特殊方法,来操作记录指针,实现随机访问:

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

其他方法:

// 指定文件的光标位置,通俗点说就是指定你的光标位置,然后下次读文件数据的时候从该位置读取。
1、seek()
// 我们注意到这是一个long类型的返回值,字面意思就是返回当前的文件光标位置。这样方便我们后面读取插入。
2、getFilePointer()
// 毫无疑问的方法,文件的长度,返回long类型。注意它并不会受光标的影响。只会反应客观的文本长度。
3、length()
// 这些方法跟readstream中的方法一样,例如最后一个:定义缓冲数组,从数组的off偏移量位置开始写,读取转换为数组数据达到len个字节。总之这是一个读文件内容的标准操作api。
4、read()、read(byte[] b)、read(byte[] b,int off,int len)
//  这些方法都是去read | write 每一个字符,个人感觉就是返回他们的ASCII码
当然如果专家们有异议可以指出,我测试的时候至少是这么感觉得。
大家也可以自己试一下。比如readLong就是要求你的文本内容必须有八个字符,不然会报错。
5、readDouble()、 readFloat()、readBoolean()、 readInt()
readLong()、 readShort()、 readByte()、 readChar()
writeDouble()、 writeFloat()、 writeBoolean()、 writeInt()
writeLong()、 writeShort() 、writeByte()、 writeChar()
// 这个方法的作用就是将文本中的内容填满这个缓冲区b。如果缓冲b不能被填满,那么读取流的过程将被阻塞,如果发现是流的结尾,那么会抛出异常。这个过程就比较像“凑齐一车人在发车,
不然不走”。
6、readFully(byte[] b): // 它返回的就是nio通信中的file的唯一channel, FileChannel 7、getChannel() // 跳过n字节的位置,相对于当前的point。 8、skipBytes(int n);

三、RandomAccessFile的使用

1:多线程写文件

利用 RandomAccessFile 实现文件的多线程下载,即多线程下载一个文件时,将文件分成几块,每块用不同的线程进行下载。下面是一个利用多线程在写文件时的例子,其中预先分配文件所需要的空间,然后在所分配的空间中进行分块,然后写入:

* 测试利用多线程进行文件的写操作 public class Test { public static void main(String[] args) throws Exception { // 预分配文件所占的磁盘空间,磁盘中会创建一个指定大小的文件 RandomAccessFile raf = new RandomAccessFile("D://abc.txt", "rw" ); raf.setLength( 1024*1024); // 预分配 1M 的文件空间 raf.close(); // 所要写入的文件内容 String s1 = "第一个字符串" ; String s2 = "第二个字符串" ; String s3 = "第三个字符串" ; String s4 = "第四个字符串" ; String s5 = "第五个字符串" ; // 利用多线程同时写入一个文件 new FileWriteThread(1024*1,s1.getBytes()).start(); // 从文件的1024字节之后开始写入数据 new FileWriteThread(1024*2,s2.getBytes()).start(); // 从文件的2048字节之后开始写入数据 new FileWriteThread(1024*3,s3.getBytes()).start(); // 从文件的3072字节之后开始写入数据 new FileWriteThread(1024*4,s4.getBytes()).start(); // 从文件的4096字节之后开始写入数据 new FileWriteThread(1024*5,s5.getBytes()).start(); // 从文件的5120字节之后开始写入数据 // 利用线程在文件的指定位置写入指定数据 static class FileWriteThread extends Thread{ private int skip; private byte [] content; public FileWriteThread( int skip, byte [] content){ this .skip = skip; this .content = content; public void run(){ RandomAccessFile raf = null ; try { raf = new RandomAccessFile("D://abc.txt", "rw" ); raf.seek(skip); raf.write(content); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { raf.close(); } catch (Exception e) { 2、使用RandomAccessFile实现从指定位置读取文件的功能

public  static void main(String[] args)throws IOException {
        String filePath="E:\\learnproject\\Iotest\\lib\\src\\main\\java\\com\\Test.txt";
        RandomAccessFile raf=null;
        File file=null;
        try {
            file=new File(filePath);
            raf=new RandomAccessFile(file,"r");
            // 获取 RandomAccessFile对象文件指针的位置,初始位置为0
            System.out.print("输入内容:"+raf.getFilePointer());
            //移动文件记录指针的位置
            raf.seek(1000);
            byte[] b=new byte[1024];
            int hasRead=0;
            //循环读取文件
            while((hasRead=raf.read(b))>0){
                //输出文件读取的内容
                System.out.print(new String(b,0,hasRead));
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            raf.close();

3、使用RandomAccessFile实现向文件中追加内容的功能

public class RandomAccessFileTest2 {
    public  static void main(String[] args)throws IOException {
        String filePath="E:\\learnproject\\Iotest\\lib\\src\\main\\java\\com\\Test.txt";
        RandomAccessFile raf=null;
        File file=null;
        try {
            file=new File(filePath);
            // 以读写的方式打开一个RandomAccessFile对象
            raf=new RandomAccessFile(file,"rw");
            //将记录指针移动到该文件的最后
            raf.seek(raf.length());
            //向文件末尾追加内容
            raf.writeChars("这是追加内容。。");
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            raf.close();

4、使用RandomAccessFile实现向文件指定位置插入内容的功能

注:RandomAccessFile  不能向文件的指定位置插入内容,如果直接将文件记录指针移动到中间某位置后开始输出,则新输出的内容会覆盖文件原有的内容,如果需要向指定位置插入内容,程序需要先把插入点后面的内容写入缓存区,等把需要插入的数据写入到文件后,再将缓存区的内容追加到文件后面。

* 插入文件指定位置的指定内容 *
@param filePath 文件路径 * @param pos 插入文件的指定位置 * @param insertContent 插入文件中的内容 * @throws IOException public static void insert(String filePath,long pos,String insertContent)throws IOException{ RandomAccessFile raf=null; File tmp=File.createTempFile("tmp",null); tmp.deleteOnExit(); try { // 以读写的方式打开一个RandomAccessFile对象 raf = new RandomAccessFile(new File(filePath), "rw"); //创建一个临时文件来保存插入点后的数据 FileOutputStream fileOutputStream = new FileOutputStream(tmp); FileInputStream fileInputStream = new FileInputStream(tmp); //把文件记录指针定位到pos位置 raf.seek(pos); raf.seek(pos); //------下面代码将插入点后的内容读入临时文件中保存----- byte[] bbuf = new byte[64]; //用于保存实际读取的字节数据 int hasRead = 0; //使用循环读取插入点后的数据 while ((hasRead = raf.read(bbuf)) != -1) { //将读取的内容写入临时文件 fileOutputStream.write(bbuf, 0, hasRead); //-----下面代码用于插入内容 ----- //把文件记录指针重新定位到pos位置 raf.seek(pos); //追加需要插入的内容 raf.write(insertContent.getBytes()); //追加临时文件中的内容 while ((hasRead = fileInputStream.read(bbuf)) != -1) { //将读取的内容写入临时文件 raf.write(bbuf, 0, hasRead); }catch (Exception e){ throw e; public static void main(String[] args)throws IOException { String filePath="E:\\learnproject\\Iotest\\lib\\src\\main\\java\\com\\Test.txt"; insert(filePath,1000,"插入指定位置指定内容");