java.io.File的renameTo方法移動文件失敗的解決方案
今天線上發(fā)現(xiàn)一個問題,發(fā)現(xiàn)一個定時移動文件的業(yè)務(wù)沒有正常執(zhí)行,結(jié)合日志和代碼發(fā)現(xiàn),移動文件是使用File類的renameTo方法,但是方法返回的都是false,表示文件移動失敗。
出現(xiàn)這個問題我第一反應(yīng)是不是文件權(quán)限的問題,但是和運維研究后發(fā)現(xiàn)的確不是權(quán)限導致的。既然不是權(quán)限的問題,那就看看renameTo的實現(xiàn)吧,查看源碼發(fā)現(xiàn)該方法最終是通過一個本地方法實現(xiàn)的,看不到咋寫的。
網(wǎng)上查了一下renameTo這個方法,發(fā)現(xiàn)這個方法確實存在一些問題,就是在不同的文件系統(tǒng)中移動是不會成功的。因為測試環(huán)境并未出現(xiàn)這個問題,我就把生產(chǎn)環(huán)境和測試環(huán)境對比了下,發(fā)現(xiàn)測試環(huán)境下,文件本身的目錄和要移動到的目錄是在/home下,而生產(chǎn)環(huán)境中,文件本身目錄是在/home下,要移動到的目錄都是在/data下。于是用df命令查看了一下,發(fā)現(xiàn) /home的文件系統(tǒng)是/dev/sda3,類型是xfs的,/data的文件系統(tǒng)是/dev/sdb1,類型是ext4。
既然是這樣那就寫個demo在自己的虛擬機上驗證一下是不是這個原因?qū)е碌摹?/p>
1.首先找兩個文件系統(tǒng)不一樣的目錄,命令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
運行結(jié)果輸出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
運行結(jié)果成功移動文件
3.apache的FileUtils移動文件方法的主要實現(xiàn)如下:
//先使用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 + "'");
}
}
總結(jié):
1、文件移動最好不要使用Java的renameTo方法,而是應(yīng)該使用apache的commons-io包,當然也可以自己封裝類似的方法。
2、renameTo方法移動失敗是文件系統(tǒng)不同造成的,補充測試發(fā)現(xiàn)不同的文件系統(tǒng),就算類型相同,移動也會失敗。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
Java Collection和Collections的區(qū)別
本文主要介紹了Java Collection和Collections的區(qū)別,Collection?是表示集合的接口,而?Collections?是對集合進行操作的工具類,下面就來介紹一下具體用法,感興趣的可以了解一下2023-12-12
idea插件之如何使用JarEditor編輯Java JAR文件
JarEditor是一款用于在IntelliJIDEA中直接編輯JAR文件的插件,支持反編譯查看和編輯.class文件,并提供即時編譯與保存功能,通過JarEditor,用戶可以在IDE內(nèi)一站式完成JAR文件的編輯、管理和打包操作,提高開發(fā)效率,但在生產(chǎn)環(huán)境中使用前,請確保備份并測試修改2025-01-01
ActiveMQ基于zookeeper的主從(levelDB Master/Slave)搭建
這篇文章主要介紹了ActiveMQ基于zookeeper的主從levelDB Master/Slave搭建,以及Spring-boot下的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-08-08
SpringBoot2.2.X用Freemarker出現(xiàn)404的解決
這篇文章主要介紹了SpringBoot2.2.X用Freemarker出現(xiàn)404的解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-02-02

