java.io.File的renameTo方法移动文件失败的解决方案

 更新时间:2021年07月07日 11:14:45   作者:东都大狼狗  
这篇文章主要介绍了java.io.File的renameTo方法移动文件失败的解决方案,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

今天线上发现一个问题,发现一个定时移动文件的业务没有正常执行,结合日志和代码发现,移动文件是使用File类的renameTo方法,但是方法返回的都是false,表示文件移动失败。

出现这个问题我第一反应是不是文件权限的问题,但是和运维研究后发现的确不是权限导致的。既然不是权限的问题,那就看看renameTo的实现吧,查看源码发现该方法最终是通过一个本地方法实现的,看不到咋写的。

网上查了一下renameTo这个方法,发现这个方法确实存在一些问题,就是在不同的文件系统中移动是不会成功的。因为测试环境并未出现这个问题,我就把生产环境和测试环境对比了下,发现测试环境下,文件本身的目录和要移动到的目录是在/home下,而生产环境中,文件本身目录是在/home下,要移动到的目录都是在/data下。于是用df命令查看了一下,发现 /home的文件系统是/dev/sda3,类型是xfs的,/data的文件系统是/dev/sdb1,类型是ext4。

既然是这样那就写个demo在自己的虚拟机上验证一下是不是这个原因导致的。

1.首先找两个文件系统不一样的目录,命令df -T

我们用/tmp 和 /run 作为测试目录。

2.测试代码

import java.io.File;
/**
* 文件移动方法测试
*/
public class FileTest {
  public static void main(String[] args) {
     String filePath="/tmp/test.txt";
     File file = new File(filePath);
     boolean b = file.renameTo(new File("/run/test.txt"));
     System.out.println(b);
 }
}

3.编译运行

javac FileTest.java
java FileTest

运行结果输出false,文件也确实未移动成功

解决方法:

使用apache的commons-io包中的工具类的进行文件移动。

1.测试代码:

import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
/**
* 文件移动方法测试
*/
public class FileTest {
  public static void main(String[] args) {
     String filePath="/tmp/test.txt";
     File file = new File(filePath);
     boolean b = file.renameTo(new File("/run/test.txt"));
     System.out.println(b);
     //使用apache的FileUtils工具
     try {
         FileUtils.moveFile(file,new File("/run/test.txt"));
         System.out.println("success");
     } catch (IOException e) {
         e.printStackTrace();
     }
 }
}

2.编译运行

javac -cp /root/jar/commons-io-2.4.jar FileTest.java
java -cp /root/jar/commons-io-2.4.jar: FileTest

运行结果成功移动文件

3.apache的FileUtils移动文件方法的主要实现如下:

//先使用renameTo方法进行移动
boolean rename = srcFile.renameTo(destFile);
if (!rename) {
 //renameTo移动失败,就复制文件,然后删除原文件
 copyFile( srcFile, destFile );
 if (!srcFile.delete()) {
 FileUtils.deleteQuietly(destFile);
 throw new IOException("Failed to delete original file '" + srcFile +
  "' after copy to '" + destFile + "'");
 }
}

总结:

1、文件移动最好不要使用Java的renameTo方法,而是应该使用apache的commons-io包,当然也可以自己封装类似的方法。

2、renameTo方法移动失败是文件系统不同造成的,补充测试发现不同的文件系统,就算类型相同,移动也会失败。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • java三层架构原理与作用小结

    java三层架构原理与作用小结

    这篇文章主要对Java三层架构的概念、作用等进行了介绍,需要的朋友可以参考下
    2017-04-04
  • Java Collection和Collections的区别

    Java Collection和Collections的区别

    本文主要介绍了Java Collection和Collections的区别,Collection 是表示集合的接口,而 Collections 是对集合进行操作的工具类,下面就来介绍一下具体用法,感兴趣的可以了解一下
    2023-12-12
  • 详解Java中ArrayList类

    详解Java中ArrayList类

    这篇文章主要介绍了Java中ArrayList类,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-03-03
  • idea插件之如何使用JarEditor编辑Java JAR文件

    idea插件之如何使用JarEditor编辑Java JAR文件

    JarEditor是一款用于在IntelliJIDEA中直接编辑JAR文件的插件,支持反编译查看和编辑.class文件,并提供即时编译与保存功能,通过JarEditor,用户可以在IDE内一站式完成JAR文件的编辑、管理和打包操作,提高开发效率,但在生产环境中使用前,请确保备份并测试修改
    2025-01-01
  • Java多线程 生产者消费者模型实例详解

    Java多线程 生产者消费者模型实例详解

    这篇文章主要介绍了Java多线程 生产者消费者模型实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Java中HashMap的put过程详解

    Java中HashMap的put过程详解

    这篇文章主要介绍了Java中HashMap的put过程详解,HashMap有4个构造器,其他构造器如果用户没有传入initialCapacity 和loadFactor这两个参数,会使用默认值一般如果new HashMap()不传值,需要的朋友可以参考下
    2023-07-07
  • 基于Java实现收发电子邮件功能

    基于Java实现收发电子邮件功能

    Email就是电子邮件,我们平常使用的QQ邮箱,网易邮箱,Foxmail都是用来收发邮件的,利用Java程序也可以完成收发电子邮件的功能,本文就来为大家详细讲讲实现步骤
    2022-07-07
  • Java使用递归回溯完美解决八皇后的问题

    Java使用递归回溯完美解决八皇后的问题

    这篇文章主要介绍了Java基于循环递归回溯实现八皇后问题算法,结合具体实例形式分析了java的遍历、递归、回溯等算法实现八皇后问题的具体步骤与相关操作技巧,需要的朋友可以参考下
    2021-11-11
  • ActiveMQ基于zookeeper的主从(levelDB Master/Slave)搭建

    ActiveMQ基于zookeeper的主从(levelDB Master/Slave)搭建

    这篇文章主要介绍了ActiveMQ基于zookeeper的主从levelDB Master/Slave搭建,以及Spring-boot下的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-08-08
  • SpringBoot2.2.X用Freemarker出现404的解决

    SpringBoot2.2.X用Freemarker出现404的解决

    这篇文章主要介绍了SpringBoot2.2.X用Freemarker出现404的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-02-02

最新评论