RN开发搬砖经验之—分析与定位图片文件被清空的原因

如题

最近工作上处理的一个BUG,先讲下结论/原因,然后再分享该主题相关的东西
结论是:copy图片文件时,源路径与目标路径相同—输入输出流同时操作同一个文件,导致文件清空了!
copy文件的主要源码如下,源代码链接是RNFSManager,JS层调最终调用到的Java方法
在这里插入图片描述

上下文

当前项目需要把应用cache目录下的文件copy至file目录下,然后由于历史代码的原因,导致产生了多次copy调用,同时代码对于copy的文件列表的管理又没有考虑到触发多次copy的情况,那么在底层库的copy方法调用时,导致copy的源文件路径跟目标文件 路径出现相等的情况,最终的结果是文件被清空了-文件size为零,没有内容!

fs库

这里用到了react-native-fs这个库
在这里插入图片描述
最新的版本是2022年,以及上面的RNFSManager中还用着AsyncTask(不是很现代),另外copyFile方法也没有考虑到源文件路径跟目标路径相等的情况!故不推荐大家继续使用该库呢

解决方案

我在项目的解决方案是/在自己的业层逻辑层做处理;
1、避免不产生多次copy文件的操作;
2、在JS层对eact-native-fs的copy方法做一层封装,当源路径与目标路径一样时,向上抛异常;

commons-io

commons-io库也有copy文件的方法,其中是有考虑到源文件路径跟目标路径相等的情况的
在这里插入图片描述

关键点

输入流未关闭的情况下,输出流操作同一路径文件,会造成冲突,输入流会认为该文件不存在并重新创建同名文件覆盖原文件,而后输入流实际读取的是一个空文件,那么输出流写入的内容也为空,最后造成文件内容置空的现象。

我们可以通过下面简单示例代码去验证或作相关的测试实验

package com.company;

import java.io.*;

public class Main {
    private static final String FILE_PATH = "/Users/luogw/Downloads/Gundam-RX-78.jpg";

    public static void printFileSize(String filePath, String tag) {
        File file = new File(filePath);
        System.out.println(String.format("File size: %d bytes, %s", file.length(), tag));
    }

    public static void main(String[] args) {
        try {
            String filepath = FILE_PATH;
            String destPath = FILE_PATH;
            printFileSize(filepath, "刚开始");
            InputStream in = new FileInputStream(filepath);
            printFileSize(destPath, "打开文件输入流");
            OutputStream out = new FileOutputStream(destPath, false);
            //如果是append模式,bug就大了!-循环读取,文件会越来越大!!
//            OutputStream out = new FileOutputStream(destPath, true);
            printFileSize(destPath, "打开文件输出流");

            byte[] buffer = new byte[1024];
            int length;
            while ((length = in.read(buffer)) > 0) {
                System.out.println(String.format("Read %d bytes", length));
                out.write(buffer, 0, length);
            }
            in.close();
            out.close();
        } catch (Exception ex) {
            ex.printStackTrace();
            System.out.println("Error");
        }
    }
}

输出结果
在这里插入图片描述

我们还可以在终端确认下文件的状态
在这里插入图片描述

其它

kimi的建议:
在这里插入图片描述

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-12 12:34:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-12 12:34:02       100 阅读
  3. 在Django里面运行非项目文件

    2024-05-12 12:34:02       82 阅读
  4. Python语言-面向对象

    2024-05-12 12:34:02       91 阅读

热门阅读

  1. C# 实现加减乘除 (备忘)

    2024-05-12 12:34:02       35 阅读
  2. 计算机视觉教学实训解决方案

    2024-05-12 12:34:02       37 阅读
  3. 1080:余数相同问题

    2024-05-12 12:34:02       30 阅读
  4. [C/C++] -- 适配器模式

    2024-05-12 12:34:02       36 阅读
  5. 整体意义的构成与构建

    2024-05-12 12:34:02       42 阅读
  6. 【负载均衡式在线OJ项目day5】OJ服务模块概要

    2024-05-12 12:34:02       35 阅读
  7. 复习用到知识(asp.net)

    2024-05-12 12:34:02       37 阅读
  8. sass详解与使用

    2024-05-12 12:34:02       34 阅读
  9. Ubuntu设置中午输入法

    2024-05-12 12:34:02       36 阅读
  10. XML 解析器

    2024-05-12 12:34:02       28 阅读