Java文件拷贝方式
原创转载请注明出处:https://www.cnblogs.com/agilestyle/p/11444284.html
利用java.io类库,直接为源文件构建一个FileInputStream读取,然后再为目标文件构建一个FileOutputStream,完成写入工作。
public static void copyFileByStream(File source, File dest) throws IOException {
try (InputStream is = new FileInputStream(source);
OutputStream os = new FileOutputStream(dest)) {
byte[] buffer = new byte[1024];
int length;
while ((length = is.read(buffer)) > 0) {
os.write(buffer, 0, length);
}
}
}
利用java.nio类库提供的transferTo或transferFrom方法实现
public static void copyFileByChannel(File source, File dest) throws IOException {
try (FileChannel sourceChannel = new FileInputStream(source).getChannel();
FileChannel targetChannel = new FileOutputStream(dest).getChannel()) {
for (long count = sourceChannel.size(); count > 0; ) {
long transferred = sourceChannel.transferTo(sourceChannel.position(), count, targetChannel);
sourceChannel.position(sourceChannel.position() + transferred);
count -= transferred;
}
}
}
Java标准类库提供的几种Files.copy的实现

对于Copy的效率,这个其实与操作系统和配置等情况相关,总体上来说,NIO transferTo/From的方式可能更快,因为它更能利用现代操作系统底层机制,避免不必要拷贝和上下文切换。
拷贝实现机制分析
先来理解一下,前面实现的不同拷贝方法,本质上有什么明显的区别。
首先,需要理解用户态空间(User Space)和内核态空间(Kernel Space),这是操作系统层面的基本概念,操作系统内核、硬件驱动等运行在内核态空间,具有相对高的特权;而用户态空间,则是给普通应用和服务使用。可以参考:https://en.wikipedia.org/wiki/User_space。
当使用输入输出流进行读写时,实际上是进行了多次上下文切换,比如应用读取数据时,先在内核态将数据从磁盘读取到内核缓存,再切换到用户态将数据从内核缓存读取到用户缓存。
写入操作也是类似,仅仅是步骤相反,可以参考下面这张图。

所以,这种方式会带来一定的额外开销,可能会降低IO效率。
而基于NIO transferTo的实现方式,在Linux和Unix上,则会使用到零拷贝技术,数据传输并不需要用户态参与,省去了上下文切换的开销和不必要的内存拷贝,进而可能提高应用拷贝性能。注意,transferTo不仅仅是可以用在文件拷贝中,与其类似的,例如读取磁盘文件,然后进行Socket发送,同样可以享受这种机制带来的性能和扩展性提高。
transferTo的传输过程是:

Reference
https://time.geekbang.org/column/article/8393
Java文件拷贝方式的更多相关文章
- 【Java面试】Java有几种文件拷贝方式,哪一种效率最高?
"Java有几种文件拷贝方式,哪一种效率最高?" 这个问题是京东一面的时候,针对4年经验的同学的一个面试题. 大家好,我是Mic,一个工作了14年的Java程序员. 关于这个问题的 ...
- java 文件拷贝
需求:源和目标! 那么我们需要源文件和目标文件! 构建管道的时候就需要两个:输出流和输入流管道! Eg: package july7file; //java7开始的自动关闭资源 import java ...
- Java文件拷贝
package com.lxm.demos; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io. ...
- Java 对象拷贝方式
(1)BeanUtils.cloneBean()使用: http://www.cnblogs.com/fervour/archive/2009/12/18/1627868.html package c ...
- IO复制多级目录 控制台输入文件目录然后把目录下java文件复制到 D: 并统计java个数
package cn.itcast_05; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; impor ...
- linux几种传输方式与拷贝方式的性能分析
本文记录linux系统中文件传输的多种方式,留作备忘.linux中文件传输的方式有ftp,scp,rsync,rz,sz等,但各个工具的功能又有所区别: FTP : FTP是文件服务器,可实现文件的上 ...
- java 四种方式实现字符流文件的拷贝对比
将D:\\应用软件\\vm.exe 拷贝到C:\\vm.exe 四种方法耗费时间对比 4>2>3>1 package Copy; import java.io.Buffere ...
- 总结java中文件拷贝剪切的5种方式-JAVA IO基础总结第五篇
本文是Java IO总结系列篇的第5篇,前篇的访问地址如下: 总结java中创建并写文件的5种方式-JAVA IO基础总结第一篇 总结java从文件中读取数据的6种方法-JAVA IO基础总结第二篇 ...
- Java IO和Java NIO在文件拷贝上的性能差异分析
1. 在JAVA传统的IO系统中,读取磁盘文件数据的过程如下: 以FileInputStream类为例,该类有一个read(byte b[])方法,byte b[]是我们要存储读取到用户空间的缓冲区 ...
随机推荐
- 运用pool进程池启动大量子进程
# Pool进程池类 from multiprocessing import Pool import os import time import random def run(index): prin ...
- element el-table 合计在横拉滚动条的下面,正确展示应该是滚动条在合计下面
<style lang="less"> .el-table{ overflow: auto; } .el-table .el-table__body-wrapper, ...
- 【串线篇】SQL映射文件EmployeeDao.xml事项
Dao.xml或者说是mapper.xml一个意思 id:方法名,相当于这个配置是对于某个方法的实现 ,参数类型不用写,()也不用写 resultType:指定方法运行后的返回值类型全类名:(查询操作 ...
- ubuntu 搜狗输入法内存占用太多,卡顿不够处理办法
1. 输入 free -m 查看是否内存不够导致卡顿 2. 输入 gnome-system-monitor 打开ubuntu 任务管理器 找到搜狗输入法结束进程 3. 完美解决
- Linux eth0, eth1, ..., eth%d 的生成【转】
转自:https://blog.csdn.net/xiruanliuwei/article/details/78765255 一直很好奇,Linux下的eth0, eth1,eth2等是如何生成的~ ...
- C++11新特性之 Move semantics(移动语义)
https://blog.csdn.net/wangshubo1989/article/details/49748703 这篇讲到了vector的push_back的两种重载版本,左值版本和右值版本.
- 那些长短不一的PCI-E插槽都有什么不一样?
https://www.ednchina.com/news/20171121-PCI-E.html 时间:2017-11-21 目前PCI-E插槽已经成为了主板上的主力扩展插槽,除了显卡会用到P ...
- Base64和3DES算法
Base64加密算法 Base64是网络上最常见的用于传输8Bit字节代码的编码方式之一,可用于在HTTP环境下传递较长的标识信息.它的优点是算法效率高,编码出来的结果比较简短,同时也具有不可读性. ...
- Network基础(一):配置计算机名及工作组、TCP/IP地址配置、网络连通性测试
一.配置计算机名及工作组 目标: 本例要求为修改计算机名并加入工作组: 设置计算机名:姓名拼音 设置工作组名:TARENA-NETWORK 方案: 修改Windows 2008服务器的计算机名(可设为 ...
- 小程序 ios 10.1.x 白屏问题
遇到这个问题有点莫名其妙只有IOS10.1.x显示白屏 解决过程很坎坷,一开始以为是调试基础库的问题,改成最新的2.9.2版本. 用这个创建新的项目,把之前的项目内容放到新建项目内, 发现还是不行,后 ...