1、字节流
在 Java 中,文件的复制使用字节输入流和字节输出流实现,java.io 包有 InputStream 和 OutputStream 这两个顶层抽象类规范了读写文件所需的核心 API。
我们可以使用它们的子类 FileInputStream 和 FileOutputStream 来编写程序复制文件。
第一种方式:
使用 read() 和 write() 方法配合循环操作单字节的读取、写入
InputStream 的 read() 会尝试从文件读取一个字节,如果到了文件结尾则会返回-1
第二种方式:
使用 read(byte[]) 和 write(byte[], int, int) 方法配合字节缓冲、循环操作实现高效的读取、写入
InputStream 的 read(byte[]) 会尝试从文件读取 byte[] 长度个字节,该方法会把具体读取到的字节数返回,如果到了文件结尾则会返回 -1
OutputStream 的 write(byte[] buf, int offest, int len) 方法会把 buf 数组中从偏移量 offest 开始的 len 个字节写到输出流
2、单字节读写
1 private static void copyFile(String src, String dst) throws IOException { 2 3 // 用于计算程序运行时间 4 long start = System.currentTimeMillis(); 5 6 // 定义输入流和输出流 7 FileInputStream fis = null; 8 FileOutputStream fos = null; 9 try { 10 11 // 实例化输入流和输出流 12 fis = new FileInputStream(src); 13 fos = new FileOutputStream(dst); 14 15 int i = fis.read(); 16 17 // 循环从输入流读取字节,直到读取到-1即文件结尾 18 while(i != -1) { 19 fos.write(i); // 写出到输出流 20 i = fis.read(); 21 } 22 } catch (IOException e) { 23 // 需要捕获IOException 24 e.printStackTrace(); 25 throw e; 26 } finally { 27 // 在finally代码块关闭IO流 28 try { 29 if (fis != null) 30 fis.close(); 31 if (fos != null) 32 fos.close(); 33 } catch (IOException e) {} 34 } 35 36 // 计算程序运行时间 37 long end = System.currentTimeMillis(); 38 System.out.println(end - start); 39 }
3、定义缓冲高效读写
1 private static void bufferedCopyFile(String src, String dst) throws IOException { 2 3 // 用于计算程序运行时间 4 long start = System.currentTimeMillis(); 5 6 // 定义输入流和输出流 7 FileInputStream fis = null; 8 FileOutputStream fos = null; 9 try { 10 11 // 实例化输入流和输出流 12 fis = new FileInputStream(src); 13 fos = new FileOutputStream(dst); 14 15 // 定义一个字节缓冲数组 16 byte[] buf = new byte[1024]; 17 int i = fis.read(buf); 18 19 // 循环从输入流尝试读取buf长度的字节存放到buf中 20 while(i != -1) { 21 fos.write(buf, 0, i); // 把buf写到输出流 22 i = fis.read(buf); 23 } 24 } catch (IOException e) { 25 // 需要捕获IOException 26 e.printStackTrace(); 27 throw e; 28 } finally { 29 // 在finally代码块关闭IO流 30 try { 31 if (fis != null) 32 fis.close(); 33 if (fos != null) 34 fos.close(); 35 } catch (IOException e) {} 36 } 37 // 计算程序运行时间 38 long end = System.currentTimeMillis(); 39 System.out.println(end - start); 40 }
4、程序运行
1 public static void main(String[] args) { 2 String src = "D:\src.bmp"; 3 String dst = "D:\tmp\java\dst.bmp"; 4 5 try { 6 7 // 单字节读写 8 copyFile(src, dst); 9 10 // 定义缓冲高效读写 11 bufferedCopyFile(src, dst); 12 } catch (IOException e) { 13 e.printStackTrace(); 14 } 15 }
输出:
21092
162
可以看到定义了缓冲区的方法要比单字节地读写效率高很多