需求分析:
- 需要实现文件的拷贝操作,那么这种拷贝就有可能拷贝各种类型的文件,所以使用字节流;
- 在进行拷贝的时候有可能需要考虑到大文件的拷贝问题;
方案设计:
- 方案一:一次性全部拷贝;
|- 如果拷贝的文件很大则此方法不可取,会导致程序崩溃
- 方案二:读取一部分输出一部分;
核心的操作:
|- InputStream: public int read(byte[] b) throws IOException;
|- OutputStream: public void write(byte[] b,int off,int len) throws IOException;
一个简单的文件拷贝操作:
import java.io.*;
class FileUntil { // 定义一个文件操作的工具类
private File srcFile; // 源文件路径
private File desFile; // 目标文件路径
public FileUntil(File srcFile,File desFile){
this.srcFile = srcFile;
this.desFile = desFile;
}
// 文件的拷贝方法
public boolean copy() throws IOException {
if (!this.srcFile.exists()){
System.out.println("源文件不存在!!");
return false;
}
if (!this.desFile.getParentFile().exists()){ // 如果目录不存在
this.desFile.getParentFile().mkdirs(); // 创建父目录
}
byte[] data = new byte[1024]; // 开辟拷贝的缓冲区
InputStream input = null;
OutputStream output = null;
try {
// 创建字节流对象
input = new FileInputStream(this.srcFile);
output = new FileOutputStream(this.desFile);
// 获取文件长度
int len = 0;
// 1.读取数据到数组之中,随后返回读取的个数,len = input.read(data)
// 2.判断个数是否是 -1,如果不是则进行写入,len = input.read(data) != -1
while ((len = input.read(data)) != -1){ // 拷贝的内容都在data数组里面
output.write(data,0,len);
}
return true;
}catch (IOException e){
e.printStackTrace();
}finally {
if (input != null){
input.close();
}
if (output != null){
output.close();
}
}
return false;
}
}
public class MAIN {
public static void main(String[] args){
long start = System.currentTimeMillis();
File src= new File("D:" + File.separator + "Demo_2_15" + File.separator + "Writer.txt");
File des= new File("D:" + File.separator + "Demo_2_15" + File.separator + "Copy.txt");
FileUntil fu = new FileUntil(src,des);
try {
fu.copy();
} catch (IOException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("拷贝完成、用时:" + (end - start) + "ms");
}
}

以上属于文件拷贝最原始的实现方式,从JDK1.9开始InputStream和Reader类中都追加有数据转存的处理操作方法:
InputStream: public long transferTo(OutputStream out) throws IOException;
Reader: public long transferTo(Writer out ) throws IOException;
使用上诉转存的操作处理:
import java.io.*;
class FileUntil { // 定义一个文件操作的工具类
private File srcFile; // 源文件路径
private File desFile; // 目标文件路径
public FileUntil(File srcFile,File desFile){
this.srcFile = srcFile;
this.desFile = desFile;
}
// 文件的拷贝方法
public boolean copy() throws IOException {
if (!this.srcFile.exists()){
System.out.println("源文件不存在!!");
return false;
}
if (!this.desFile.getParentFile().exists()){ // 如果目录不存在
this.desFile.getParentFile().mkdirs(); // 创建父目录
}
InputStream input = null;
OutputStream output = null;
try {
// 创建字节流对象
input = new FileInputStream(this.srcFile);
output = new FileOutputStream(this.desFile);
input.transferTo(output);
return true;
}catch (IOException e){
e.printStackTrace();
}finally {
if (input != null){
input.close();
}
if (output != null){
output.close();
}
}
return false;
}
}
public class MAIN {
public static void main(String[] args){
long start = System.currentTimeMillis();
File src= new File("D:" + File.separator + "Demo_2_15" + File.separator + "Writer.txt");
File des= new File("D:" + File.separator + "Demo_2_15" + File.separator + "Copy.txt");
FileUntil fu = new FileUntil(src,des);
try {
fu.copy();
} catch (IOException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("拷贝完成、用时:" + (end - start) + "ms");
}
}
这种方法的性能更好,但是需要更高的JDK版本要求。
连带目录的拷贝功能:
import java.io.*;
import java.lang.reflect.Field;
class FileUntil { // 定义一个文件操作的工具类
private File srcFile; // 源文件路径
private File desFile; // 目标文件路径
public FileUntil(File srcFile,File desFile){
this.srcFile = srcFile;
this.desFile = desFile;
}
public boolean copyDir() throws IOException{
if (!this.srcFile.exists()){
System.out.println("拷贝目录不存在!");
return false;
}
try {
this.copyDirImpl(this.srcFile);
return true;
}catch (Exception e){
return false;
}
}
private boolean copyDirImpl(File file) throws IOException{
if (file.isDirectory()){ // 是目录
File[] allDir = file.listFiles(); // 列出目录下所有内容
System.out.println(allDir.length);
if (allDir != null){ // 如果目录不为空
for (File dir : allDir) { // 遍历目录
copyDirImpl(dir); // 递归操作
}
}
}else{ // 是文件
String newfilePath = file.getPath().replace(this.srcFile.getPath() + File.separator,""); // 替换文件路径的父路径,找到文件名
System.out.println(newfilePath);
File newFile = new File(this.desFile,newfilePath); // 将目标路径作为父路径
this.copyFileImpl(file,newFile); // 调用拷贝方法
}
return false;
}
private boolean copyFileImpl(File srcFile, File desFile) throws IOException{
if (!desFile.getParentFile().exists()){ // 如果目录不存在
desFile.getParentFile().mkdirs(); // 创建父目录
}
InputStream input = null;
OutputStream output = null;
try {
// 创建字节流对象
input = new FileInputStream(srcFile);
output = new FileOutputStream(desFile);
input.transferTo(output); // 直接使用转存方法
return true;
}catch (IOException e){
e.printStackTrace();
}finally {
if (input != null){
input.close();
}
if (output != null){
output.close();
}
}
return false;
}
// 文件的拷贝方法
public boolean copyFile() throws IOException {
if (!this.srcFile.exists()){
System.out.println("源文件不存在!!");
return false;
}
return this.copyFileImpl(this.srcFile,this.desFile);
}
}
public class MAIN {
public static void main(String[] args){
long start = System.currentTimeMillis();
// File src= new File("D:" + File.separator + "Demo_2_15" + File.separator + "Writer.txt");
File src= new File("D:" + File.separator + "Demo_2_15"); // 源目录
File des= new File("D:" + File.separator + "Demo_2_17"); // 目标目录
FileUntil fu = new FileUntil(src,des);
try {
if (src.isFile()){ // 文件拷贝
System.out.println(fu.copyFile()? "拷贝成功" : "拷贝失败");
}else { // 目录拷贝
System.out.println(fu.copyDir()? "拷贝成功" : "拷贝失败");
}
} catch (IOException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("拷贝完成、用时:" + (end - start) + "ms");
}
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)