一)FileChannel介绍
概述:用于读取,写入,映射和操作文件的通道。
它只能通过调用getChannel()方式创建FileChannel对象,不能直接new FileChannel()。
优点:
1、对大文件操作支持比较好,文件访问和传输速度快。
2、支持多线程。
3、数据不易丢失。
二)FileChannel案例详解
方式一:使用FileChannel通道类中的API
方法说明:
1、static FileChannel open(Path path, OpenOption... options)
打开或创建文件,返回文件通道以访问该文件。
2、static FileChannel open(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs)
打开或创建文件,返回文件通道以访问该文件。
3、abstract long transferTo(long position, long count, WritableByteChannel target)
将该通道文件的字节传输到给定的可写字节通道。用来从FileChannel到其它通道的数据传输。
4、abstract long transferFrom(ReadableByteChannel src, long position, long count)
从给定的可读字节通道将字节传输到该通道的文件中。允许从源通道到FileChannel的数据传输。
源码实现:
/**
* 方式一:直接使用通道类中的API
*/
public static void method1() {
long start = System.currentTimeMillis();
FileChannel in = null;
FileChannel out =null;
try {
// 通过Paths获取源文件的路径,StandardOpenOption.READ 读取模式
in = FileChannel.open(Paths.get("D:\\io\\446MB.rar"), StandardOpenOption.READ);
out = FileChannel.open(Paths.get("D:\\io\\abab.rar"), StandardOpenOption.READ
, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
//把数据读到 输出通道中取,完成文件的复制
//in.transferTo(0,in.size(),out);
// 强制将此通道文件的任何更新写入包含该通道的存储设备。
out.force(false);
// 写出数据,写出的数据从输入通道中来
out.transferFrom(in, 0, in.size());
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("拷贝文件,总共耗时" + (end-start) + "ms");
}
方式二:使用MappedByteBuffer字节缓冲器
方法说明:
1、abstract MappedByteBuffer map(FileChannel.MapMode mode, long position, long size)
将此频道文件的区域直接映射到内存中。
源码实现:
/**
* 方式二:使用MappedByteBuffer字节缓冲器
*/
public static void method2() {
long start = System.currentTimeMillis();
FileChannel in = null;
FileChannel out =null;
try {
// 通过Paths获取源文件的路径,StandardOpenOption.READ 读取模式
in = FileChannel.open(Paths.get("D:\\io\\446MB.rar"), StandardOpenOption.READ);
out = FileChannel.open(Paths.get("D:\\io\\abab.rar"), StandardOpenOption.READ
, StandardOpenOption.WRITE, StandardOpenOption.CREATE);
// 操作内存映射文件(也就是这个缓冲区在物理内存中)
MappedByteBuffer inByteBuffer = in.map(FileChannel.MapMode.READ_ONLY, 0, in.size());
MappedByteBuffer outByteBuffer = out.map(FileChannel.MapMode.READ_WRITE, 0, in.size());
// 直接对缓冲区进行读写操作
byte[] bytes = new byte[inByteBuffer.limit()];
inByteBuffer.get(bytes);
outByteBuffer.put(bytes);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("拷贝文件,总共耗时" + (end-start) + "ms");
}
方式三:使用RandomAccessFile实例
方法说明:
1、RandomAccessFile(File file, String mode)
创建一个随机访问文件流从File参数指定的文件中读取,并可选地写入文件。
2、RandomAccessFile(String name, String mode)
创建随机访问文件流,以从中指定名称的文件读取,并可选择写入文件。
备注:mode的模式包含“r”、“rw”、“rws”、“rwd”共4种模式。
源码实现:
public static void method3() {
long start = System.currentTimeMillis();
RandomAccessFile randomFile = null;
FileChannel inChannel = null;
try {
randomFile = new RandomAccessFile("D:\\io\\a.txt", "rw");
inChannel = randomFile.getChannel();
// 缓冲区
ByteBuffer buf = ByteBuffer.allocate(48);
int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {
buf.flip(); // 从写模式转换成读模式
// 打印
while (buf.hasRemaining()) {
System.out.print((char)buf.get());
}
buf.clear(); // 清理缓存,重新读写
bytesRead = inChannel.read(buf);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inChannel != null) {
inChannel.close();
}
if (randomFile != null) {
randomFile.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("拷贝文件,总共耗时" + (end-start) + "ms");
}
方式四:使用FileInputStream字节输入流和FileOutputStream字节输出流中getChannel()
源码实现:
/**
* 方式四:使用FileInputStream字节输入流和FileOutputStream字节输出流中getChannel()
*/
public static void method4() {
long start = System.currentTimeMillis();
FileInputStream in = null;
FileOutputStream out = null;
FileChannel inChannel = null;
FileChannel outChannel =null;
try {
// 创建文件输入输出流
in = new FileInputStream("D:\\io\\6_81MB.xlsx");
out = new FileOutputStream("D:\\io\\abcd.xlsx");
// 文件输入输出流的getChannel()方法获取通道
inChannel = in.getChannel();
outChannel = out.getChannel();
// 获取非直接缓冲区
//ByteBuffer buf = ByteBuffer.wrap(new byte[1024*8]);
ByteBuffer buf = ByteBuffer.allocate(256);
int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {
buf.flip(); // 从写模式转换成读模式
// 将缓冲区中的数据写入通道中
outChannel.write(buf);
buf.clear(); // 清空缓冲区并返回对缓冲区的引用
bytesRead = inChannel.read(buf);
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (inChannel != null) {
inChannel.close();
}
if (outChannel != null) {
outChannel.close();
}
if (in != null) {
in.close();
}
if (out != null) {
out.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
long end = System.currentTimeMillis();
System.out.println("拷贝文件,总共耗时" + (end-start) + "ms");
}
识别二维码关注个人微信公众号
本章完结,待续,欢迎转载!
本文说明:该文章属于原创,如需转载,请标明文章转载来源!