栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java中使用renameTo方法导致文件数据缺失

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java中使用renameTo方法导致文件数据缺失

开发的时候发现了es里面数据有缺失,排查了好久,最后怀疑是renameTo方法的时候,在renameTo还没有完成的时候,程序就对生成的文件进行了处理,实际上这个时候文件还没有完全进入目标文件夹

这完全是一个偶发的问题,但是,发生的频率并不算太低,基本上每小时12个点的文件,总会有一个点出现这种情况,我并没有做完全的统计,因为总体数据量比较大。

于是我在renameTo操作后加了一个线程等待一秒钟的操作,就是为了防止出现这种文件还未转移完全的情况

并且我打印了两行日志,看一下被renameTo前后文件是不是有差异

结果果然是,renameTo前后的数据竟然相差相当大

我研究了一下renameTo的源码,发现最后是调用的native方法

private native boolean rename0(File f1, File f2);

我猜测是rename0方法是在开始执行的时候,发现文件可以移动就返回了true,而此时其实刚开始执行数据移动操作,数据移动还没有完成,理论上这种移动会很快。程序进行操作的文件,13000行的数据,也没有产生问题,为什么2000行的数据会缺失。是不是如果遇到了机器IO极大的时候,可能会影响数据的转移。在转移了部分数据之后,我的程序开始了读操作,然后就出现了不可写入的情况。剩下的数据也就不会再写入了。

但是伴随而来的就是一个问题,rename0方法到底是以什么形式进行转移文件的,未完全转移的时候是否允许对文件进行读写操作。如果允许,那么我猜测可能成立,如果不允许,我的猜测就不成立了。

我开始想调大一点sleep时间,但是每一秒对于上万个文件的处理速度都是很大的影响。我现在发现,我甚至没办法判断rename0是否完成了。

最后处理办法决定通过复制再删除的方法完成试一下,原来的renameTo换成了jdk提供的一个FileChannel的方式实现

                try {
                    FileUtil.copyFileUsingFileChannels(backFile,backuppath);
                    backFile.delete();
                }catch (Exception e){
                    LOGGER.error("文件复制失败:"+backPath);
                }

copyFileUsingFileChannels方法

    public static void copyFileUsingFileChannels(File source, File dest)
            throws IOException {
        FileChannel inputChannel = null;
        FileChannel outputChannel = null;
        try {
            inputChannel = new FileInputStream(source).getChannel();
            outputChannel = new FileOutputStream(dest).getChannel();
            outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
        } finally {
            inputChannel.close();
            outputChannel.close();
        }
    }

目前观察程序还没有出现缺失数据的情况,待后续观察

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/332345.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号