RandomAccessFile是java输入/输出流体系中功能最丰富的问几十年内容访问类,它提供了众多的方法来访问文件内容,它既可以读取文件内容,也可以向文件输出数据。与普通的输入/输出流不同的是,RandomAccessFile支持“随机访问”的方式。程序可以直接跳转到文件的任意地方来读写数据。

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

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

 

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

RandomAccessFile对象也包含了一个记录指针,用以标识当前读写的位置,当程序新创建一个RandomAccessFile对象时,该对象的文件记录指针位于文件头,但读/写了N个字节后,文件记录指针将会向后移动N个字节。初次之外,RandomAccessFile可以自由移动该记录指针,既可以向前移动,也可以向后移动。RandomAccessFile包含了如下两个方法来操作文件记录指针。

1:long getFilePointer():返回文件记录指针的当前位置。

2:void seek(long pos): 将文件记录指针定位到pos位置。

 

RandomAccessFile既可以读文件,也可以写,所以它即包含了完全类似与InputStream的三个read()方法,其用法和InputStream的三个read()方法完全一样;也包含了完全类似于OutputStream的三个write()方法,其用法和OutputStream的三个Write()方法完全一样。除此之外,RandomAccessFile还包含了一些列的readXxx()和WriteXxx()方法来完成输入,输出。

 

RandomAccessFile有两个构造器,其实这两个构造器基本相同,只是指定文件的形式不同而已,一个使用String参数来指定文件名,一个使用File参数来指定文件本身。除此之外创建RandomAccessFile对象时还需要指定一个mode参数,该参数指定RandomAccessFile的访问模式,该参数有如下四个值。

"r": 以只读方式打开指定文件,如果视图对该RandomAccessFile执行写入方法,将抛出异常。

"rw":以读/写方式打开指定文件。如果该文件不存在,则尝试创建该文件。

"rws":以读/写方式打开指定文件。相对于"rw"模式,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。

"rwd":以读/写方式打开指定文件。相对于"rw"模式,还要求对文件的内容的每个更新都同步写入到底层存储设备。

 

下面程序使用了RandomAccessFile来访问指定的中间部分数据。

 1 public class RandomAccessFileTest
 2 {
 3     public static void main(String[] args) 
 4     {
 5         try(
 6             RandomAccessFile raf = new RandomAccessFile("a.txt", "r"))
 7         {
 8             //获取RandomAccessFile对象文件指针的位置,初始位置是0
 9             System.out.println("RandomAccessFile的文件初始位置:" + raf.getFilePointer());
10             //移动raf的文件记录指针位置
11             raf.seek(300);
12             byte[] by = new byte[1024];
13             
14             //用于保存实际读取的字节数
15             int hasRead = 0;
16             
17             //读取
18             while((hasRead = raf.read(by)) > 0)
19             {
20                 //将字节数组转换为字符串
21                 System.out.println(new String(by, 0, hasRead));
22             }
23         }
24         catch(IOException ex)
25         {
26             ex.printStackTrace();
27         }
28                 
29                 
30     }
31 }

上面程序创建了RandomAccessFile对象,该对象以只读方式打开了a.tat文件,这意味着该RandomAccessFile对象只能读取文件内容,不能执行写入。程序中将文件记录指针定位到300处,也就是说,程序将从300字节处开始读,程序接下来的部分与使用InputStream读取并没有太大的区别。

 

 下面程序示范了如何向指定文件后追加内容,为了追加内容,程序应该先将记录指针移动到文件最后,然后开始向文件中输出内容。

public class AppendContent 
{

    public static void main(String[] args) 
    {
        try(
                //以读,写方式打开一个RandomAccessFile对象
                RandomAccessFile raf = new RandomAccessFile("a.txt", "rw"))
        {
            //将记录指针移动法哦文件最后
            raf.seek(raf.length());
            raf.write("追加的内容!\r\n".getBytes());
        }
        catch(IOException ex)
        {
            ex.printStackTrace();
        }

    }

}

上面的程序以读/写的方式创建了RandomAccessFile对象,将对象的记录指针移动到最后;接下来使用RandomAccessFile执行输出,与使用OutputStream或Writer执行并没有太大区别。

 

 

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

 

下面的程序实现了向指定文件,指定位置插入内容的功能

 1 public class InsertContent
 2 {
 3     public static void insert(String fileName, long pos, String insertContent) throws IOException
 4     {
 5         File tem = File.createTempFile("tmp", null);
 6         tem.deleteOnExit();
 7         try(
 8                 RandomAccessFile raf = new RandomAccessFile(fileName, "rw");
 9                 //使用临时文件来保存插入点后的数据
10                 FileOutputStream tmpOut = new FileOutputStream("tmp");
11                 FileInputStream tmpIn = new FileInputStream("tmp"))
12         {
13             raf.seek(pos);
14             //-----下面的代码将插入点后的内容读入临时文件中保存-----
15             byte[] by = new byte[64];
16             //用于保存实际读取的字节数
17             int hasRead;
18             //使用循环方式读取插入点后的数据
19             while((hasRead = raf.read(by)) > 0)
20             {
21                 //将读取的数据写入临时文件
22                 tmpOut.write(by, 0, hasRead);
23             }
24             
25             //-----下面的代码用于插入内容-----
26             //把文件记录指针重新定位到pos位置
27             raf.seek(pos);
28             
29             //追加需要插入的内容
30             raf.write(insertContent.getBytes());
31             
32             //追加临时文件中的内容
33             while((hasRead = tmpIn.read(by)) > 0)
34             {
35                 raf.write(by, 0, hasRead);
36             }
37         }
38     }
39     public static void main(String[] args) throws IOException 
40     {
41         insert("a.txt", 45, "插入的内容\r\n");
42     }
43 }

 

posted on 2016-02-26 05:41  所谓荣耀  阅读(810)  评论(0编辑  收藏  举报