FileChannel

一个FileChannel 实例只能通过在一个打开的file对象(RandomAccessFile、FileInputStream或 FileOutputStream)上调用getChannel( )方法获取.调用getChannel( )方法会返回一个连接到相同文件的FileChannel 对象且该FileChannel 对象具有与file对象相同的访问权限。然后您就可以使用该通道对象来利用强大的FileCh annel API了。

RandomAccessFile 类与通道都是差不多。在通道出现之前,底层的文件操作都是通过RandomAccessFile 类的方法来实现的。FileChannel 模拟同样的I/O服务,因此它的API自然也是很相似的。
为了便于比较,表 3-1 列出了FileChannel 、RandomAccessFile 和POSIX I/O system calls三者在方法上的对应关系:
[img]http://dl.iteye.com/upload/attachment/0078/3930/6b2ec803-4119-3f3e-9957-1ec5ccc6ec92.png[/img]

请看下面使用fileChannel进行文件的copy:
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class ChannelCopy {

private static final int BSIZE =1024;
public static void main(String[] args) {
try {
FileChannel in = new FileInputStream("ChannelCopy.java").getChannel(),out = new FileOutputStream("D:\\temp.txt").getChannel();
ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
while((in.read(buffer))!=-1){
buffer.flip();//做好被写的准备
out.write(buffer);
buffer.clear();//做好被读的准备
}
} catch (FileNotFoundException e) {
System.out.println("找不到文件");
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**简单写法**/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;

public class CopyOfChannel2 {
public static void main(String[] args) {
try {
FileChannel in = new FileInputStream("ChannelCopy.java").getChannel(), out = new FileOutputStream("D:\\temp.txt").getChannel();
in.transferTo(0, in.size(), out);//简便写法
out.transferFrom(in, 0, in.size());//效果同上
} catch (FileNotFoundException e) {
System.out.println("找不到文件");
} catch (IOException e) {
e.printStackTrace();
}
}
}


2. 内存映射文件
由map()方法返回的MappedByteBuffer对象的行为在多数方面类似一个基于内存的缓冲区,只
不过该对象的数据元素存储在磁盘上的一个文件中。
通过内存映射机制来访问一个文件会比使用常规方法读写高效得多,甚至比使用通道的效率都
高。因为不需要做明确的系统调用,那会很消耗时间。更重要的是,操作系统的虚拟内存可以自动缓存内存页(memory page)。这些页是用系统内存来缓存的,所以不会消耗Java 虚拟机内存堆 (memory heap)。

我们可以创建一个MappedByteBuffer来代表一个文件中字节的某个子范围。例如,要映射 100 到299(包含299)位置的字节,可以使用下面的代码:

buffer = fileChannel.map (FileChannel.MapMode.READ_ONLY, 100, 200);

如果要映射整个文件则使用:
buffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, fileChannel.size());

MapMode.READ_ONLY和MapMode.READ_WRITE 意义是很明显的 第三种模式MapMode.PRIVATE 表示您想要一个写时拷贝(copy -on-write)的映射。这意味着您通过put( )方法所做的任何修改都会导致产生一个私有的数据拷贝并且该拷贝中的数据只有MappedByteBuffer实例可以看到。该过程不会对底层文件做任何修改,而且一旦缓冲区被施以垃圾收集动作(garbage collected ),那些修改都会丢失。尽管写时拷贝的映射可以防止底层文件被修改,您也必须以read/write权限来打开文件以建立MapMode.PRIVATE 映射。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值