java-NIO-FileChannel(文件IO)
Java NIO中的FileChannel是一个连接到文件的通道。可以通过文件通道读写文件。
FileChannel无法设置为非阻塞模式,它总是运行在阻塞模式下。
对于文件的复制,平时我们都是使用输入输出流进行操作,利用源文件创建出一个输入流,然后利用目标文件创建出一个输出流,最后将输入流的数据读取写入到输出流中。这样也是可以进行操作的。但是利用fileChannel是很有用的一个方式。它能直接连接输入输出流的文件通道,将数据直接写入到目标文件中去。而且效率更高。
FileChannel是一个用读写,映射和操作一个文件的通道。除了读写操作之外,还有裁剪特定大小文件truncate(),强制在内存中的数据刷新到硬盘中去force(),对通道上锁lock()等功能。
他们的使用分别如下面代码:
ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
//读取1024字节内容到byteBuffer钟
fileChannelInput.read(byteBuffer);
解释:上面代码首先创建一个1024大小的缓冲对象,然后在输入通道中读取1024大小数据,放入到缓冲对象中。
byteBuffer.clear();
byteBuffer.put("需要写入的数据".getBytes());
//类似于flush()函数功能,将buffer里面的数据刷新出去
byteBuffer.flip();
//检查是否还有数据未写入
while (byteBuffer.hasRemaining())
fileChannelOutput.write(byteBuffer);
解释:上面的代码是将一段字符串写入到输出文件通道中,因为写入的时候并不保证能一次性写入到文件中,所以需要进行判断是否全部写入,如果没有需要再次调用写入函数操作
//获取文件通道位置
fileChannelInput.position();
fileChannelInput.size();
//截取内容
fileChannelInput.truncate(1024);
//强制刷新数据到硬盘
fileChannelInput.force(true);
解释:上面的代码是获取文件通道的位置和大小。truncate()方法是截取1024大小的数据,指定长度后面的部分将被删除。以及将数据强制刷新到硬盘中,因为系统会将数据先保存在内存中,不保证数据会立即写入到硬盘中,所以有这个需求,就可以直接强制数据写入内存中。
使用
说那么多可能没用,我们还是直接来看看分别使用两种方法进行文件复制的对比。
首先是普通的输入输出流进行复制文件:
import org.springframework.util.ResourceUtils; import java.io.*; /**
* 普通的文件复制
*/
public class FileCopyForNomal {
public void fileCopy(File fromFile,File toFile){
InputStream inputStream = null;
OutputStream outputStream = null; try {
inputStream = new BufferedInputStream(new FileInputStream(fromFile));
outputStream = new BufferedOutputStream(new FileOutputStream(toFile,true));//追加
byte [] bytes = new byte[1024];
int i;
while((i=inputStream.read(bytes)) != -1){
outputStream.write(bytes,0,i);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(inputStream!=null){
inputStream.close();
}if(outputStream!=null){
outputStream.close();
}
}catch (IOException e){
e.printStackTrace();
}
}
} public static void main(String[] args) throws FileNotFoundException {
String from = ResourceUtils.getFile("classpath:a.txt").getPath();//这边文件是在target下
System.out.println(from);
String to = ResourceUtils.getFile("classpath:b.txt").getPath();//这边文件是在target下
System.out.println(to);
File fromFile = new File(from);
File toFile = new File(to); Long startTime = System.currentTimeMillis();
new FileCopyForNomal().fileCopy(fromFile,toFile);
Long endTime = System.currentTimeMillis();
System.out.println(endTime-startTime);
}
}
结果:
G:\idea_workspace\io\filechannel\target\classes\a.txt
G:\idea_workspace\io\filechannel\target\classes\b.txt
48
下面再看一下利用fileChannel进行文件的复制操作。
import org.springframework.util.ResourceUtils; import java.io.*;
import java.nio.channels.FileChannel; /**
* 通道文件复制
*/
public class FileCopyForChannel {
public void fileCopy(File fromFile, File toFile){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
FileChannel fileChannelInput = null;
FileChannel fileChannelOutput = null;
try {
fileInputStream = new FileInputStream(fromFile);
fileOutputStream = new FileOutputStream(toFile);
//得到fileInputStream的文件通道
fileChannelInput = fileInputStream.getChannel();
//得到fileOutputStream的文件通道
fileChannelOutput = fileOutputStream.getChannel();
//将fileChannelInput通道的数据,写入到fileOutputStream中
fileChannelInput.transferTo(0,fileChannelInput.size(),fileChannelOutput);
}catch(IOException e){
e.printStackTrace();
}finally {
try {
if (fileInputStream != null)
fileInputStream.close();
if (fileChannelInput != null)
fileChannelInput.close();
if (fileOutputStream != null)
fileOutputStream.close();
if (fileChannelOutput != null)
fileChannelOutput.close();
} catch (IOException e) {
e.printStackTrace();
}
}
} public static void main(String[] args) throws FileNotFoundException {
String from = ResourceUtils.getFile("classpath:a.txt").getPath();//这边文件是在target下
System.out.println(from);
String to = ResourceUtils.getFile("classpath:b.txt").getPath();//这边文件是在target下
System.out.println(to);
File fromFile = new File(from);
File toFile = new File(to); Long startTime = System.currentTimeMillis();
new FileCopyForChannel().fileCopy(fromFile,toFile);
Long endTime = System.currentTimeMillis();
System.out.println(endTime-startTime);
}
}
结果:
G:\idea_workspace\io\filechannel\target\classes\a.txt
G:\idea_workspace\io\filechannel\target\classes\b.txt
22
运行代码之后,复制一个文件,对比两种复制方法,发现利用filechannel使用的时间比普通的读取输入时间缩短了将近一半。尤其是在进行大文件复制的时候,filechannel显得更加有优势。
总结
这里我们了解了FileChannel类,知道了它所具有的特点和功能,那么我们就可以好好的使用它了。尤其是在我们复制文件的时候,可以更好的利用这个类,可以提高效率,也可以防止出现oom等其它情况。
源码地址:https://github.com/qjm201000/io_nio_filechannel.git
java-NIO-FileChannel(文件IO)的更多相关文章
- Java NIO FileChannel
A Java NIO FileChannel is a channel that is connected to a file. Using a file channel you can read d ...
- JAVA NIO FileChannel 内存映射文件
文件通道总是阻塞式的. 文件通道不能创建,只能通过(RandomAccessFile.FileInputStream.FileOutputStream)getChannel()获得,具有与File ...
- Java IO和Java NIO在文件拷贝上的性能差异分析
1. 在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区 ...
- 【原创】java NIO FileChannel 学习笔记 FileChannel 简介
java NIO 中FileChannel 的实现类是 FileChannelImpl,FileChannel本身是一个抽象类. 先介绍FileChannel File Channels 是线程安全 ...
- JAVA NIO之文件通道
1.简介 通道是 Java NIO 的核心内容之一,在使用上,通道需和缓存类(ByteBuffer)配合完成读写等操作.与传统的流式 IO 中数据单向流动不同,通道中的数据可以双向流动.通道既可以读, ...
- Java NIO 读取文件、写入文件、读取写入混合
前言 Java NIO(new/inputstream outputstream)使用通道.缓冲来操作流,所以要深刻理解这些概念,尤其是,缓冲中的数据结构(当前位置(position).限制(limi ...
- java nio 映射文件内容到内存
FileChannel 的一个最好的功能就是能将文件的某个部分直接映射到内存.这要感谢 FileChannel.map() 方法,这个方法有下面三个参数: mode:映射到内存需要指定下面三种模式之一 ...
- java输入输出 -- java NIO之文件通道
一.简介 通道是 Java NIO 的核心内容之一,在使用上,通道需和缓存类(ByteBuffer)配合完成读写等操作.与传统的流式 IO 中数据单向流动不同,通道中的数据可以双向流动.通道既可以读, ...
- 3,Java中的文件IO流
1,File类 ··· 概念:File对象可以表示一个文件或目录.可以对其进行增删改查. ··· 常用方法: File f = new File("."); 判断是 ...
- Java NIO.2 —— 文件或目录移动操作
移动文件树是复制和删除的文件树的结合.实际上,有两种方式来完成文件的移动.一种是使用Files.move(), Files.copy(), 和Files.delete() 这三个方法:另一种是只使用F ...
随机推荐
- Cocos2d-x 3.0final 终结者系列教程09-漆节点Node中间Schedule
怎么做HelloWorld工程HelloWorld文字实现它自己主动运动? 有的童鞋会想到使用线程.不断的变化Label的Position, 不要那样做,因为Cocos2d-x在主线程只能被改变Nod ...
- 谷歌推出备份新工具:Google Drive将同步计算机文件
Google 正在将云端硬盘 Drive 转变成更强大的文件备份工具.很快,Google Drive 将能监测并备份你电脑上的(几乎)所有文件,只要是你勾选的文档,Drive 就能同步至云端. 具体来 ...
- MyBatis Generator 详解 专题
idea中有plugin可提高效率: http://www.henryxi.com/use-idea-mybatis-plugin-generate-mapper-files eg: <?xml ...
- 源码编译路径错误导致的Apache 无法重启问题解决方法
问题现象: 第一次源码编译安装Apache设置路径错误,安装到/usr/local/src/ 目录下了. 删掉该目录下的安装文件,重新编译安装到/usr/local/目录下 重启apache服务时报这 ...
- js div的显示和隐藏
<head> <title></title> <style type="text/css"> div ...
- Qt浮动按钮的实现(使用窗口背景透明、实现只显示浮动按钮的目的)
Qt浮动按钮的实现 效果如下: 图3 估计很多做Qt有一定经验的朋友会觉得这个效果不难,但是这是一个需求奇葩的实际业务中做出的效果.笔者会想讲下客户的需求和整体框架的矛盾. 整个项目主要是由Qt搭建的 ...
- Win10如何设置开机自动登录
原文:Win10如何设置开机自动登录 第一步: 小娜搜索"netplwiz",进入用户账户设置. 第二步: 先勾选选中一次,要使用本计算机,用户必须输入用户名和密码. 第三步: 取 ...
- Android 开发相关
1.app下载更新 https://git.oschina.net/lwngreat/UpdateHelper
- 什么是OTC?
OTC(Over The Counter)非处方药物,我国卫生部医政司是这样定义的:它是消费者可不经过医生处方,直接从药房或药店购买的药品,而且是不在医疗专业人员指导下就能安全使用的药品,即不需要凭借 ...
- 1.预处理,生成预编译文件(.文件): Gcc –E hello.c –o hello.i 2.编译,生成汇编代码(.s文件): Gcc –S hello.i –o hello.s 3.汇编,生成目标文件(.o文件): Gcc –c hello.s –o hello.o 4.链接,生成可执行文件: linux笔记
1 动态查看日志 tail -f filename tail -1000f filename 2 解压当前目录内容为xxx.zip zip -r xxx.zip ./* 3 查看内存使用情况 fre ...