java实现文件拷贝的七种方式

作者:zhaojiaxing0216 时间:2023-07-20 19:01:41 

1. 通过字节流实现文件的拷贝


/**
  * 通过字节流实现文件的拷贝
  * @param sourcePath 源文件路径
  * @param targetPath 目标文件路径
  */
 public static void copyFileByStream(String sourcePath,String targetPath){
   //源文件路径
   File source = new File(sourcePath);
   //目标文件路径
   File target = new File(targetPath);

//如果源文件不存在则不能拷贝
   if(!source.exists()){
     return;
   }
   //如果目标文件目录不存在则创建
   if(!target.getParentFile().exists()){
     target.getParentFile().mkdirs();
   }

try {
     //实现文件的拷贝
     InputStream inputStream = new FileInputStream(source);
     OutputStream outputStream = new FileOutputStream(target);
     int temp = 0;
     //每次读取1024个字节
     byte[] data = new byte[1024];
     //将每次读取的数据保存到字节数组里面,并且返回读取的个数
     while ((temp = inputStream.read(data)) != -1){
       //输出数组
       outputStream.write(data,0,temp);
     }

inputStream.close();
     outputStream.close();
   } catch (IOException e) {
     e.printStackTrace();
   }
 }

2. 通过字符流实现文件拷贝

使用字符流只能拷贝文本文件


 /**
  * 通过字符流实现文件的拷贝
  *
  * @param sourcePath 源文件路径
  * @param targetPath 目标文件路径
  */
 public static void copyFileByReaderAndWriter(String sourcePath, String targetPath) {
   //源文件路径
   File source = new File(sourcePath);
   //目标文件路径
   File target = new File(targetPath);

//如果源文件不存在则不能拷贝
   if (!source.exists()) {
     return;
   }
   //如果目标文件目录不存在则创建
   if (!target.getParentFile().exists()) {
     target.getParentFile().mkdirs();
   }

FileReader in = null;
   FileWriter out = null;
   try {
     //字符输入流和字符输出流
     in = new FileReader(source);
     out = new FileWriter(target);

char[] c = new char[1024];
     int temp = 0;
     //每次读取1024个字符
     while ((temp = in.read(c)) != -1) {
       //输出到文件
       out.write(c, 0, temp);
     }
   } catch (IOException e) {
     e.printStackTrace();
   } finally {
     //关闭流
     try {
       if (in != null) {
         in.close();
       }
       if (out != null) {
         out.close();
       }
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

3. 通过字节缓冲流实现文件拷贝


/**
  * 通过字节缓冲流实现文件的拷贝
  *
  * @param sourcePath 源文件路径
  * @param targetPath 目标文件路径
  */
 public static void copyFileByBuffered(String sourcePath, String targetPath){
   //源文件路径
   File source = new File(sourcePath);
   //目标文件路径
   File target = new File(targetPath);

//如果源文件不存在则不能拷贝
   if (!source.exists()) {
     return;
   }
   //如果目标文件目录不存在则创建
   if (!target.getParentFile().exists()) {
     target.getParentFile().mkdirs();
   }

InputStream in = null;
   OutputStream out = null;
   try {
     //字节缓冲输入流和字节缓冲输出流
     in = new BufferedInputStream(new FileInputStream(source));
     out = new BufferedOutputStream(new FileOutputStream(target));

byte[] b = new byte[1024];
     int temp = 0;
     //每次读取一个1024的字节数组
     while((temp = in.read(b)) != -1){
       //输出到文件
       out.write(b,0,temp);
     }
   } catch (Exception e) {
     e.printStackTrace();
   }finally {
     //关闭流
     try {
       if (in != null) {
         in.close();
       }
       if (out != null) {
         out.close();
       }
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

4. 通过字符缓冲流拷贝文件

字符缓冲流只能读取文本文件


/**
  * 通过字符缓冲流实现文件的拷贝
  *
  * @param sourcePath 源文件路径
  * @param targetPath 目标文件路径
  */
 public static void copyFileByBufferedChar(String sourcePath, String targetPath){
   //源文件路径
   File source = new File(sourcePath);
   //目标文件路径
   File target = new File(targetPath);

//如果源文件不存在则不能拷贝
   if (!source.exists()) {
     return;
   }
   //如果目标文件目录不存在则创建
   if (!target.getParentFile().exists()) {
     target.getParentFile().mkdirs();
   }

BufferedReader in = null;
   BufferedWriter out = null;

try {
     //字符缓冲输入流和字符缓冲输出流
     in = new BufferedReader(new FileReader(source));
     out = new BufferedWriter(new FileWriter(target));

//读取文件(每次读取一行)
     String temp = null;
     while((temp = in.readLine()) != null){
       //输出到文件
       out.write(temp);
     }

} catch (Exception e) {
     e.printStackTrace();
   }finally {
     //关闭流
     try {
       if (in != null) {
         in.close();
       }
       if (out != null) {
         out.close();
       }
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

5. 通过JAVA NIO 非直接缓冲区拷贝文件


 /**
  * 通过JAVA NIO 非直接缓冲区拷贝文件
  *
  * @param sourcePath 源文件路径
  * @param targetPath 目标文件路径
  */
 public static void copyFileByChannel(String sourcePath, String targetPath) {
   FileChannel outChannel = null;
   FileChannel inChannel = null;

FileInputStream fis = null;
   FileOutputStream fos = null;

try {
     fis = new FileInputStream(sourcePath);
     fos = new FileOutputStream(targetPath);

//获取通道
     inChannel = fis.getChannel();
     outChannel = fos.getChannel();

//分配指定大小的缓冲区
     ByteBuffer buf = ByteBuffer.allocate(1024);

while (inChannel.read(buf) != -1) {
       //转换为读取数据模式
       buf.flip();
       //写入到磁盘
       outChannel.write(buf);
       //清空缓冲区
       buf.clear();
     }

} catch (Exception e) {
     e.printStackTrace();
   } finally {
     //关闭流
     try {
       if (outChannel != null) {
         outChannel.close();
       }
       if (inChannel != null) {
         inChannel.close();
       }
       if (fis != null) {
         fis.close();
       }
       if (fos != null) {
         fos.close();
       }
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

6. 通过JAVA NIO 直接缓冲区拷贝文件


/**
  * 通过JAVA NIO 直接缓冲区拷贝文件(内存映射文件)
  *
  * @param sourcePath 源文件路径
  * @param targetPath 目标文件路径
  */
 public static void copyFileByChannelBufferd(String sourcePath, String targetPath) {
   FileChannel inChannel = null;
   FileChannel outChannel = null;
   try {
     //获取通道,StandardOpenOption.READ表示可读,StandardOpenOption.WRITE表示可写,StandardOpenOption.CREATE表示可以创建
     inChannel = FileChannel.open(Paths.get(sourcePath), StandardOpenOption.READ);
     outChannel = FileChannel.open(Paths.get(targetPath), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);

//创建内存映射文件
     MappedByteBuffer inMapped = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size());
     MappedByteBuffer outMapped = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size());

//直接操作内存映射文件
     byte[] buf = new byte[inMapped.limit()];
     inMapped.get(buf);
     outMapped.put(buf);

} catch (IOException e) {
     e.printStackTrace();
   } finally {
     //关闭流
     try {
       if (outChannel != null) {
         outChannel.close();
       }
       if (inChannel != null) {
         inChannel.close();
       }
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

7. 通过JAVA NIO 通道传输拷贝文件

方式一


/**
  * 通过JAVA NIO 通道传输拷贝文件
  *
  * @param sourcePath 源文件路径
  * @param targetPath 目标文件路径
  */
 public static void copyFileByChannelTransfer(String sourcePath, String targetPath) {
   FileChannel inChannel = null;
   FileChannel outChannel = null;
   try {
     //获取通道
     inChannel = FileChannel.open(Paths.get(sourcePath), StandardOpenOption.READ);
     outChannel = FileChannel.open(Paths.get(targetPath),StandardOpenOption.WRITE,StandardOpenOption.READ,StandardOpenOption.CREATE);

inChannel.transferTo(0,inChannel.size(),outChannel);
   } catch (IOException e) {
     e.printStackTrace();
   }finally {
     //关闭流
     try {
       if (outChannel != null) {
         outChannel.close();
       }
       if (inChannel != null) {
         inChannel.close();
       }
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

方式二


/**
  * 通过JAVA NIO 通道传输拷贝文件
  *
  * @param sourcePath 源文件路径
  * @param targetPath 目标文件路径
  */
 public static void copyFileByChannelTransfer2(String sourcePath, String targetPath) {
   FileInputStream fis = null;
   FileOutputStream fos = null;
   FileChannel inChannel = null;
   FileChannel outChannel = null;
   try {
     fis = new FileInputStream(sourcePath);
     fos = new FileOutputStream(targetPath);

//获取通道
     inChannel = fis.getChannel();
     outChannel = fos.getChannel();

inChannel.transferTo(0,inChannel.size(),outChannel);
   } catch (IOException e) {
     e.printStackTrace();
   }finally {
     //关闭流
     try {
       if (outChannel != null) {
         outChannel.close();
       }
       if (inChannel != null) {
         inChannel.close();
       }
     } catch (IOException e) {
       e.printStackTrace();
     }
   }
 }

使用示例


   String source = "e:\\demo\\纵天神帝.txt";
   String target = "e:\\demo\\";
   long time1 = System.currentTimeMillis();
   copyFileByStream(source, target + "1.txt");
   System.out.println("通过字节流实现文件的拷贝耗时:" + (System.currentTimeMillis() - time1));

long time2 = System.currentTimeMillis();
   copyFileByReaderAndWriter(source, target + "2.txt");
   System.out.println("通过字符流实现文件的拷贝耗时:" + (System.currentTimeMillis() - time2));

long time3 = System.currentTimeMillis();
   copyFileByBuffered(source, target + "3.txt");
   System.out.println("通过字节缓冲流实现文件的拷贝耗时:" + (System.currentTimeMillis() - time3));

long time4 = System.currentTimeMillis();
   copyFileByBufferedChar(source, target + "4.txt");
   System.out.println("通过字符缓冲流实现文件的拷贝耗时:" + (System.currentTimeMillis() - time4));

long time5 = System.currentTimeMillis();
   copyFileByChannel(source, target + "5.txt");
   System.out.println("通过JAVA NIO通道(非直接缓冲区)实现文件的拷贝耗时:" + (System.currentTimeMillis() - time5));

long time6 = System.currentTimeMillis();
   copyFileByChannelBufferd(source, target + "6.txt");
   System.out.println("通过JAVA NIO通道(直接缓冲区)实现文件的拷贝耗时:" + (System.currentTimeMillis() - time6));

long time7 = System.currentTimeMillis();
   copyFileByChannelTransfer(source, target + "7.txt");
   System.out.println("通过JAVA NIO通道传输实现文件的拷贝耗时:" + (System.currentTimeMillis() - time7));

long time8 = System.currentTimeMillis();
   copyFileByChannelTransfer(source, target + "8.txt");
   System.out.println("通过JAVA NIO通道传输2实现文件的拷贝耗时:" + (System.currentTimeMillis() - time8));

通过测试发现,使用JAVA NIO通道传输、JAVA NIO通道直接缓冲区以及字节缓冲流拷贝文件效率最高

来源:https://blog.csdn.net/zjx2016/article/details/104160069

标签:java,文件拷贝
0
投稿

猜你喜欢

  • 解析从源码分析常见的基于Array的数据结构动态扩容机制的详解

    2021-07-19 09:01:03
  • Android实现仿360桌面悬浮清理内存

    2021-08-25 11:21:05
  • servlet异步请求的实现

    2023-07-14 17:11:38
  • c# 动态构建LINQ查询表达式

    2022-03-23 20:40:47
  • 深入解析kafka 架构原理

    2023-11-18 13:40:14
  • Moshi 完美解决Gson在kotlin中默认值空的问题详解

    2022-10-29 00:03:19
  • 以Java代码为例讲解设计模式中的简单工厂模式

    2023-02-09 15:14:17
  • Mybatis查询时,区分大小写操作

    2021-08-11 14:10:54
  • WPF实现平面三角形3D运动效果

    2021-10-25 02:35:02
  • C#在RichTextBox中显示不同颜色文字的方法

    2023-01-03 17:36:06
  • 浅谈Java操作符与其优先级

    2022-09-27 19:42:44
  • SpringBoot2.0 ZipKin示例代码

    2022-11-25 00:24:40
  • Spring Cloud项目前后端分离跨域的操作

    2022-05-20 08:11:16
  • Android实时文件夹创建方法

    2023-11-30 03:13:42
  • Unity通用泛型单例设计模式(普通型和继承自MonoBehaviour)

    2023-08-24 14:53:28
  • 快速了解Java中ThreadLocal类

    2021-06-28 03:32:20
  • Android10 启动之SystemServer源码分析

    2021-08-15 05:38:13
  • HashMap 和 Hashtable的区别

    2022-11-01 06:34:47
  • Java中break、continue、return在for循环中的使用

    2023-03-21 23:36:05
  • Android实现滑动效果

    2022-09-20 15:04:24
  • asp之家 软件编程 m.aspxhome.com