缓冲流

对于节点流FileReader、FileWriter以及FileInputStream、FileOutputStream,真实开发场景中很少直接用,一般都会配合使用处理流(如缓冲流),来提高文件的处理效率。

缓冲流

为了提高数据读写的速度,Java API提供了带缓冲功能的流类,在使用这些流类时,会创建一个内部缓冲区数组,缺省使用8192个字节(8Kb)的缓冲区。

缓冲流要“套接”在相应的节点流之上,根据数据操作单位可以把缓冲流分为:

  • BufferedInputStream、BufferedOutputStream
  • BufferedReader、BufferedWriter

文件复制

修改之前使用字节流实现的文件复制功能,该用缓冲流。然后,测试下效率高了多少。

public class FileUtil {

    public static void copy (File src, File dst) throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dst);
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            byte[] bytes = new byte[1024];
            int len;
            while ((len = bis.read(bytes)) > -1) {              
                // 这里不需要flush操作,因为write方法里已经用了flush操作。
                bos.write(bytes, 0, len);
            }
        } catch (IOException e) {
           throw e;
        } finally {
            if (bis != null) {
                bis.close();
            }

            if (bos != null) {
                bos.close();
            }
        }
    }
}

注意,应该先关闭外层流,再关闭内存流。(形象比喻:穿衣先穿内衣再穿外衣,脱衣先脱外衣再脱内衣)。另外,只需要关闭最外层流,内存流就会自动关闭。

测试代码如下:

 File src = new File("C:\迅雷下载\海贼王-480.mp4");
File dst = new File("dir/1.mp4");

long start = System.currentTimeMillis();

try {
    FileUtil.copy(src, dst);
} catch (IOException e) {
    e.printStackTrace();
}

System.out.println(System.currentTimeMillis() - start); 

效率从1857毫秒变成了379.提升的效率非常明显。

图片加密与解密

package com.studyjava.gwx.IO;

import java.io.*;

/**
 * @author monkeykingGWX
 * email 704835519@qq.com
 * created 2021-03-13 19:46
 */

public class FileUtil {

   ……
    // 文件加密
    public static void encrypt (File src, File dst) throws IOException {
        FileInputStream fis = null;
        FileOutputStream fos = null;
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;

        try {
            fis = new FileInputStream(src);
            fos = new FileOutputStream(dst);
            bis = new BufferedInputStream(fis);
            bos = new BufferedOutputStream(fos);

            byte[] bytes = new byte[1024];
            int len;
            while ((len = bis.read(bytes)) > -1) {
                for (int i = 0; i < len; i ++) {
                    bytes[i] = (byte) (bytes[i] ^ 5);
                }

                // 这里不需要flush操作,因为write方法里已经用了flush操作。
                bos.write(bytes, 0, len);
            }
        } catch (IOException e) {
            throw e;
        } finally {
            if (bis != null) {
                bis.close();
            }

            if (bos != null) {
                bos.close();
            }
        }
    }

    // 文件解密
    public static void decrypt (File src, File dst) throws IOException {
        encrypt(src, dst);
    }
}

测试代码如下

 // 图片加密
File src = new File("dir/1.jpg");
File dst = new File("dir/encrypt.jpg");

try {
    FileUtil.encrypt(src, dst);
} catch (IOException e) {
    e.printStackTrace();
}

// 图片解密
try {
    FileUtil.decrypt(dst, new File("dir/decrypt.jpg"));
} catch (IOException e) {
    e.printStackTrace();
}
Posted in: IO