package com.pangwen.usefultools.io;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
/**
* 文件拷贝工具类 * Created on 2017/4/18.
*
* @author pangwen
* @version 0.1
*/public final class FileCopyUtils {
/**
* 大于500M的文件为大文件 */ private static final long BIG_FILE_SIZE = 1024 * 1024 * 500;
/**
* byte[]默认长度为1024 */ private static final int BUFFER_SIZE = 1024;
/**
* 最大线程数 */ private static final int MAX_THREAD_NUM = 5;
/**
* 静态内部类实现多线程 */ private static class FileCopyWorker implements Runnable {
private final File srcFile;
private final File targetFile;
private final long startPosition;
private final long endPosition;
/**
* constructor * * @param srcFile 源文件
* @param targetFile 目标文件
* @param startPosition 文件开始位置
* @param endPosition 文件结束位置
*/ public FileCopyWorker(final File srcFile, final File targetFile, final long startPosition, final long endPosition) {
this.srcFile = srcFile;
this.targetFile = targetFile;
this.startPosition = startPosition;
this.endPosition = endPosition;
}
//@Override
public void run() {
RandomAccessFile rin = null;
RandomAccessFile rout = null;
try {
rin = new RandomAccessFile(srcFile, "r");
rin.seek(startPosition);
rout = new RandomAccessFile(targetFile, "rw");
rout.seek(startPosition);
byte[] buffer = new byte[BUFFER_SIZE];
int i;
int readLength = 0;
while ((i = rin.read(buffer)) != -1 && startPosition + readLength <= endPosition) {
rout.write(buffer, 0, i);
readLength += i;
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != rin)
rin.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (null != rout)
rout.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
/**
* nio拷贝文件 * * @param srcFile 源文件
* @param targetFile 目标文件
*/
public static void copyFileNio(final File srcFile, final File targetFile) throws FileNotFoundException {
if (null == srcFile)
throw new FileNotFoundException("src file not found!");
makeParentDirs(targetFile);
FileInputStream in = new FileInputStream(srcFile);
FileOutputStream out = new FileOutputStream(targetFile);
//获取通道
FileChannel inChannel = null;
FileChannel outChannel = null;
try {
inChannel = in.getChannel();
outChannel = out.getChannel();
//创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
//将数据读入缓冲区
while (inChannel.read(buffer) != -1) {
//flip() 方法让缓冲区可以将新读入的数据写入另一个通道。
buffer.flip();
//将缓冲区数据写入文件
outChannel.write(buffer);
//clear() 方法重设缓冲区,使它可以接受读入的数据。
buffer.clear();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (inChannel != null) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (outChannel != null) {
try {
outChannel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 拷贝文件 * * @param srcFile 源文件
* @param targetFile 目标文件
* @param allowMultipleThread 是否开启多线程
* @throws FileNotFoundException
*/ public static void copyFile(final File srcFile, final File targetFile, final boolean allowMultipleThread) throws FileNotFoundException {
if (null == srcFile)
throw new FileNotFoundException("src file not found!");
//创建父文件夹
makeParentDirs(targetFile);
long srcFileLength = srcFile.length();
if (allowMultipleThread && srcFileLength > BIG_FILE_SIZE) {
try {
//大文件调用多线程
copyFileMultipleThread(srcFile, targetFile);
return; } catch (Exception e) {
e.printStackTrace();
//多线程拷贝文件失败时调用单线程拷贝文件
copyFile(srcFile, targetFile, false);
}
}
FileInputStream in = null;
FileOutputStream out = null;
try {
in = new FileInputStream(srcFile);
out = new FileOutputStream(targetFile);
byte[] buffer = new byte[BUFFER_SIZE];
int i;
while ((i = in.read(buffer)) != -1) {
out.write(buffer, 0, i);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != in)
in.close();
} catch (Exception e) {
e.printStackTrace();
}
try {
if (null != out)
out.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* 多线程拷贝文件 RandomAccessFile * * @param srcFile 源文件
* @param targetFile 目标文件
*/ private static void copyFileMultipleThread(final File srcFile, final File targetFile) {
final long srcFileLength = srcFile.length();
int threadNum = (int) (srcFileLength / BIG_FILE_SIZE);
if (threadNum > MAX_THREAD_NUM)
threadNum = MAX_THREAD_NUM;
long residuumFileLength = srcFileLength % threadNum;
//每份文件大小
long perFileSize = (srcFileLength - residuumFileLength) / threadNum;
//开始位置
long startPosition = 0;
//结束位置
long endPosition = perFileSize;
for (int i = 0; i < threadNum; i++) {
new Thread(new FileCopyWorker(srcFile, targetFile, startPosition, endPosition)).start();
//下一现场读取文件开始位置
startPosition = endPosition + 1;
//下一现场读取文件结束位置
endPosition += perFileSize;
//最后一个线程读取到文件末
if (i == threadNum - 2)
endPosition = srcFileLength;
}
}
private static void makeParentDirs(final File file) throws FileNotFoundException {
if (null == file)
throw new FileNotFoundException("target file must not be null!");
File parent = file.getParentFile();
if (!parent.exists())
parent.mkdirs();
}
private FileCopyUtils() {
throw new IllegalAccessError("can not create instance!");
}
}
近期热议
推荐标签 标签
-
小薇
34 引用 • 467 回帖 • 693 关注
小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。
由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!
-
人工智能
75 引用 • 145 回帖 • 1 关注
人工智能(Artificial Intelligence)是研究、开发用于模拟、延伸和扩展人的智能的理论、方法、技术及应用系统的一门技术科学。
-
PostgreSQL
22 引用 • 22 回帖
PostgreSQL 是一款功能强大的企业级数据库系统,在 BSD 开源许可证下发布。
-
Sillot
15 引用 • 6 回帖 • 28 关注
Sillot (汐洛)孵化自思源笔记,致力于服务智慧新彖乄,具有彖乄驱动、极致优雅、开发者友好的特点
Github 地址:https://github.com/Hi-Windom/Sillot -
Latke
70 引用 • 532 回帖 • 712 关注
Latke 是一款以 JSON 为主的 Java Web 框架。
-
Jenkins
51 引用 • 37 回帖
Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。
-
Logseq
4 引用 • 55 回帖 • 10 关注
Logseq 是一个隐私优先、开源的知识库工具。
Logseq is a joyful, open-source outliner that works on top of local plain-text Markdown and Org-mode files. Use it to write, organize and share your thoughts, keep your to-do list, and build your own digital garden.
-
CSDN
14 引用 • 155 回帖
CSDN (Chinese Software Developer Network) 创立于 1999 年,是中国的 IT 社区和服务平台,为中国的软件开发者和 IT 从业者提供知识传播、职业发展、软件开发等全生命周期服务,满足他们在职业发展中学习及共享知识和信息、建立职业发展社交圈、通过软件开发实现技术商业化等刚性需求。
-
ZooKeeper
59 引用 • 29 回帖 • 18 关注
ZooKeeper 是一个分布式的,开放源码的分布式应用程序协调服务,是 Google 的 Chubby 一个开源的实现,是 Hadoop 和 HBase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。
-
链滴
131 引用 • 3639 回帖
链滴是一个记录生活的地方。
记录生活,连接点滴
-
架构
140 引用 • 441 回帖 • 1 关注
我们平时所说的“架构”主要是指软件架构,这是有关软件整体结构与组件的抽象描述,用于指导软件系统各个方面的设计。另外还有“业务架构”、“网络架构”、“硬件架构”等细分领域。
-
Vue.js
261 引用 • 662 回帖
Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。
-
反馈
123 引用 • 906 回帖 • 193 关注
Communication channel for makers and users.
-
HTML
103 引用 • 294 回帖
HTML5 是 HTML 下一个的主要修订版本,现在仍处于发展阶段。广义论及 HTML5 时,实际指的是包括 HTML、CSS 和 JavaScript 在内的一套技术组合。
-
Caddy
10 引用 • 54 回帖 • 126 关注
Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。
-
Openfire
6 引用 • 7 回帖 • 89 关注
Openfire 是开源的、基于可拓展通讯和表示协议 (XMPP)、采用 Java 编程语言开发的实时协作服务器。Openfire 的效率很高,单台服务器可支持上万并发用户。
-
LeetCode
209 引用 • 72 回帖 • 2 关注
LeetCode(力扣)是一个全球极客挚爱的高质量技术成长平台,想要学习和提升专业能力从这里开始,充足技术干货等你来啃,轻松拿下 Dream Offer!
-
TextBundle
1 引用 • 2 回帖 • 47 关注
TextBundle 文件格式旨在应用程序之间交换 Markdown 或 Fountain 之类的纯文本文件时,提供更无缝的用户体验。
-
Hexo
21 引用 • 140 回帖 • 28 关注
Hexo 是一款快速、简洁且高效的博客框架,使用 Node.js 编写。
-
WebClipper
3 引用 • 9 回帖 • 6 关注
Web Clipper 是一款浏览器剪藏扩展,它可以帮助你把网页内容剪藏到本地。
-
PHP
164 引用 • 407 回帖 • 526 关注
PHP(Hypertext Preprocessor)是一种开源脚本语言。语法吸收了 C 语言、 Java 和 Perl 的特点,主要适用于 Web 开发领域,据说是世界上最好的编程语言。
-
音乐
59 引用 • 509 回帖
你听到信仰的声音了么?
-
MySQL
675 引用 • 535 回帖 • 1 关注
MySQL 是一个关系型数据库管理系统,由瑞典 MySQL AB 公司开发,目前属于 Oracle 公司。MySQL 是最流行的关系型数据库管理系统之一。
-
锤子科技
4 引用 • 31 回帖 • 10 关注
锤子科技(Smartisan)成立于 2012 年 5 月,是一家制造移动互联网终端设备的公司,公司的使命是用完美主义的工匠精神,打造用户体验一流的数码消费类产品(智能手机为主),改善人们的生活质量。
-
快应用
15 引用 • 127 回帖 • 2 关注
快应用 是基于手机硬件平台的新型应用形态;标准是由主流手机厂商组成的快应用联盟联合制定;快应用标准的诞生将在研发接口、能力接入、开发者服务等层面建设标准平台;以平台化的生态模式对个人开发者和企业开发者全品类开放。
-
ZeroNet
1 引用 • 21 回帖 • 592 关注
ZeroNet 是一个基于比特币加密技术和 BT 网络技术的去中心化的、开放开源的网络和交流系统。
- Solo
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于