2024-10-03_IO流实践

starrylsi
2024-10-03 / 0 评论 / 10 阅读 / 正在检测是否收录...
文件复制可以使用封装好的 files.copy(),也可以使用原生的

需求 3: 分别使用文件流和缓冲流复制一个长度大于 100MB 的视频文件,并观察效率的差异。

  • 问题: 不知道在文件复制时先使用哪一个
  • 关键: 输入流就是在读取数据,输出流就是在写数据
  • 理解清楚两个概念:

    • 输入流是 Java 中用于从不同数据源读取数据的流
    • 输出流是 Java 中用于将数据写入不同目的地的流

使用文件流复制

为什么需要这两段代码?
第一段代码设置了文件读取和写入的“通道”。
第二段代码实现了文件内容的实际复制。

 String sourceFile = "H:\\My_Life_Archive\\Entertainment-娱乐\\VID_20210916_082147.mp4";
        String destFile = "H:\\My_Life_Archive\\Entertainment-娱乐\\outputVideo.mp4";

        // 使用文件流复制文件
        long startTime = System.currentTimeMillis();
        // 第一段:创建输入输出流对象
        try (FileInputStream readVideo = new FileInputStream(sourceFile);
             FileOutputStream writeVideo = new FileOutputStream(destFile)) {
                //第二段:读取和写入数据
            int byteData;
            while ((byteData = readVideo.read()) != -1) {
                writeVideo.write(byteData);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();
        System.out.println("文件流复制耗时:" + (endTime - startTime) + "ms");

使用缓冲流复制

创建通道
设置缓冲数组大小
判断是否文件末尾
写入数据
关闭流

String sourceFile = "H:\\My_Life_Archive\\Entertainment-娱乐\\VID_20210916_082147.mp4";
String destFile = "H:\\My_Life_Archive\\Entertainment-娱乐\\outputVideo.mp4";
long startTime = System.currentTimeMillis();
//1.创建通道
try {
    BufferedInputStream bufferedReadVideo = new BufferedInputStream(new FileInputStream(sourceFile));
    BufferedOutputStream bufferedWriteVideo = new BufferedOutputStream(new FileOutputStream(destFile));
    //2.复制内容
    byte[] buffer = new byte[1024*1024];
    int bytesRead;
    while ((bytesRead = bufferedReadVideo.read(buffer)) != -1) {
        bufferedWriteVideo.write(buffer, 0, bytesRead);
    }
    bufferedWriteVideo.flush();
} catch (IOException e) {
    e.printStackTrace();
}

long endTime = System.currentTimeMillis();
System.out.println("文件流复制耗时:" + (endTime - startTime) + "ms");

需求 4: 复制文件夹 d:/java 下面所有文件和子文件夹内容到 d:/java2。

前置知识

  • listFiles() 方法被调用以获取目录下的所有文件和子目录。
  • 使用 java.nio.file.Files.copy() 方法来复制一个文件。这里使用了两个 toPath() 方法将 java.io.File 对象转换成 java.nio.file.Path 对象,以便于使用 Files.copy() 方法进行文件复制

代码实现

/**
     * 复制一个目录及其内容到另一个位置。
     *
     * @param src 源目录
     * @param dest 目标目录
     */
private static void copyFolder(File src, File dest) {
// checks
if(src==null || dest==null)
    return;
if(!src.isDirectory())
    return;
if(dest.exists()){
    if(!dest.isDirectory()){
        //System.out.println("destination not a folder " + dest);
        return;
    }
} else {
    dest.mkdir();
}

File[] files = src.listFiles();
if(files==null || files.length==0)
    return;

for(File file: files){
    File fileDest = new File(dest, file.getName());
    //System.out.println(fileDest.getAbsolutePath());
    if(file.isDirectory()){
        copyFolder(file, fileDest);
    }else{
        if(fileDest.exists())
            continue;

        try {
            Files.copy(file.toPath(), fileDest.toPath());
        } catch (IOException e) {
            //e.printStackTrace();
        }
    }
}
}

我总结的关键步骤(符合我编写的步骤)

第一步: 把复制文件的逻辑编写好
  1. 获取文件列表
  2. 循环列表
  3. 初始化目标文件对象
  4. 判断是否为目录,是就回调本身,不是就复制
第二步: 考虑结束递归的条件
  1. 确保传入的 src 和 dest 参数都是有效的(非 null)。
  2. 确保 src 是一个目录。
  3. 确保 dest 要么是一个已存在的目录,要么是一个可以成功创建的新目录。

AI 总结的整体步骤

参数检查:

if (src == null || dest == null):确保源目录和目标目录都不为 null。
if (!src.isDirectory()):确保源目录确实是一个目录。
if (dest.exists()):检查目标目录是否已经存在。
如果存在且不是一个目录,则直接返回。
如果不存在,则尝试创建目录

获取目录内容:

File[] files = src.listFiles();:获取源目录下的所有文件和子目录。

遍历目录内容:

for (File file : files):遍历目录下的所有文件和子目录。
如果遇到子目录,则递归调用 copyFolder 方法继续复制。
如果遇到普通文件,则检查目标文件是否已存在。
如果已存在,则跳过复制。
如果不存在,则使用 Files.copy 方法复制文件,并使用 REPLACE_EXISTING 选项确保如果目标文件存在则被替换。

0

评论 (0)

取消