Bootstrap

JAVA字节流实现复制文件的几种方式

一、方式一

public static void demo1() throws FileNotFoundException, IOException {
   FileInputStream fis = new FileInputStream("res.jpg");      //创建输入流对象,关联res.jpg
   FileOutputStream fos = new FileOutputStream("copy.jpg");   //创建输出流对象,关联copy.jpg
   
   int b;
   while((b = fis.read()) != -1) {                         //在不断的读取每一个字节
      fos.write(b);                                //将每一个字节写出
   }
   
   fis.close();                                    //关流释放资源
   fos.close();
}

缺点:该方式一次读写一个字节,复制大文件时效率低下

二、方式二

 intavailable()
          返回下一次对此输入流调用的方法可以不受阻塞地从此输入流读取(或跳过)的估计剩余字节数。
public static void demo2() throws FileNotFoundException, IOException {
   FileInputStream fis = new FileInputStream("res.mp3");     //创建输入流对象,关联res.mp3
   FileOutputStream fos = new FileOutputStream("copy.mp3");   //创建输出流对象,关联copy.mp3

   byte[] arr = new byte[fis.available()];                   //创建与文件一样大小的字节数组
   fis.read(arr);                                  //将文件上的字节读取到内存中
   fos.write(arr);                                     //将字节数组中的字节数据写到文件上
   
   fis.close();
   fos.close();
}

缺点:不推荐使用,因为有可能会导致内存溢出

三、方式三(小数组)

public static void main(String[] args) throws IOException {
   FileInputStream fis = new FileInputStream("res.mp3");
   FileOutputStream fos = new FileOutputStream("copy.mp3");
   
   byte[] arr = new byte[1024 * 8];
   int len;
   while((len = fis.read(arr)) != -1) {       //如果忘记加arr,返回的就不是读取的字节个数,而是字节的码表值
      fos.write(arr,0,len);
   }
   
   fis.close();
   fos.close();
}

四、方式四(缓冲流)(推荐)

1.缓冲思想

字节流一次读写一个数组的速度明显比一次读写一个字节的速度快很多,这是加入了数组这样的缓冲区效果,java本身在设计的时候,也考虑到了这样的设计思想(装饰设计模式后面讲解),所以提供了字节缓冲区流。

2.BufferedInputStream

BufferedInputStream内置了一个缓冲区(数组),从BufferedInputStream中读取一个字节时,BufferedInputStream会一次性从文件中读取8192个, 存在缓冲区中, 返回给程序一个,程序再次读取时, 就不用找文件了, 直接从缓冲区中获取,直到缓冲区中所有的都被使用过, 才重新从文件中读取8192个。

private static int DEFAULT_BUFFER_SIZE = 8192;
BufferedInputStream(InputStream in)
          创建一个 BufferedInputStream 并保存其参数,即输入流 in,以便将来使用。

注:可由InputStream类的子类作为参数构建

3.BufferedOutputStream

BufferedOutputStream也内置了一个缓冲区(数组),程序向流中写出字节时, 不会直接写到文件, 先写到缓冲区中,直到缓冲区写满, BufferedOutputStream才会把缓冲区中的数据一次性写到文件里。

BufferedOutputStream(OutputStream out)
          创建一个新的缓冲输出流,以将数据写入指定的底层输出流。

4.复制文件代码

public static void main(String[] args) throws IOException {
   BufferedInputStream bis = new BufferedInputStream(new FileInputStream("res.mp3"));
   BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream("copy.mp3"));
   
   int b;
   while((b = bis.read()) != -1) {
      bos.write(b);
   }
   bis.close();
   bos.close();
}

5.flush和close方法的区别

  • flush()方法

       用来刷新缓冲区的,刷新后可以再次写出 

  • close()方法

       用来关闭流释放资源的,如果是带缓冲区的流对象的close()方法,不但会关闭流,还会再关闭流之前刷新缓冲区,关闭后不能再写出 

       注:带缓冲区的流对象若没有关闭流,则可能会导致缓冲区中的部分数据未刷新到文件中,导致写出数据丢失

;