Java SE 7 新特性之文件操作(7) - 随机读写文件

时间:2021-12-10 18:04:20

转自 开发者的天空


随机访问文件 允许我们不按照顺序的访问文件的内容,这 里的访问包括读和写。要随机的访问文件,我们就要打开文件,定位到指定的位置,然后读或写文件内容。在Javs SE 7中,SeekableByteChannel接口提供了这个功能。
SeekableByteChannel提供了一些简单易用的方法。依靠这些方法,我们能够设置或查询当前的位置,然后从当前位置读或者往当前位置写。该 接口提供的方法有:
    * position – 查询通道当前的位置
    * position(long) – 设置通道当前的位置
    * read(ByteBuffer) – 从通道向缓冲区读字节内容
    * write(ByteBffer) – 将缓冲区内的字节内容写入通道
    * truncate(long) – 截断连接到通道的文件(或其他实体)
在实际的使用中,我们可以用Path .newByteChannel获取一个 SeekableByteChannel实例。在缺省的文件系统上,我们可以直接使用该实例,或者将其转换成FileChannel。 FileChannel提供了一些更高级的特性,如将文件的一部分直接映射到内存中来提高访问速度、锁定文件的一部分、直接在指定的绝对位置读或写而不影 响通道的当前位置等。

下面的例子中,我们打开了一个文件,然后将返回的SeekableByteChannel转换成FileChannel,然后开始我们的文件操作 。首先我们从头开始读取12个字节,然后我们 重新定位到文件开头,从这里开始写如'I was here!/n'。然后我们定位到文件的尾部,再一次添加'I was here!/n',然后将读取的文件的前12个字节添加到这里。

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

                String s = "I was here!/n";
                byte data[] = s.getBytes();
                ByteBuffer out = ByteBuffer.wrap(data);

                ByteBuffer copy = ByteBuffer.allocate(12);
                FileChannel fc = null;
                Path file = Paths.get("c://testChannel.txt");

                try {
                    fc = (FileChannel)file.newByteChannel(StandardOpenOption.READ, StandardOpenOption.WRITE);

                    //Read the first 12 bytes of the file.
                    int nread;
                    do {
                        nread = fc.read(copy);
                    } while (nread != -1 && copy.hasRemaining());

                    //Write "I was here!" at the beginning of the file.
                    fc.position(0);
                    while (out.hasRemaining())
                        fc.write(out);
                    out.rewind();

                    /*Move to the end of the file, write "I was here!" again,then copy the first 12 bytes to the end of the file.*/
                    long length = fc.size();
                    fc.position(length);
                    while (out.hasRemaining())
                        fc.write(out);
                    copy.flip();
                    while (copy.hasRemaining())
                        fc.write(copy);
                } catch (IOException x) {
                    System.out.println("I/O Exception: " + x);
                } finally {
                    //Close the file.
                    if (fc != null) fc.close();
                    System.out.println(file + " has been modified!");
                }

假设原来的文件内容为
123456789ABCDEF
那么程序执行之后,文件的内容变化为
I was here!
DEFI was here!
123456789ABC

需要注意的是,当定位到文件的末尾是,位置是fc.size(), 并没有减1。如果减了1,原来的文件中最后一个字节会被覆盖。