请慎用java的File#renameTo(File)方法(转载)

原文地址:http://xiaoych.iteye.com/blog/149328

以前我一直以为File#renameTo(File)方法与OS下面的 move/mv 命令是相同的,可以达到改名、移动文件的目的。不过后来经常发现问题:File#renameTo(File)方法会返回失败(false),文件没有移动,又查不出原因,再后来干脆弃用该方法,自己实现一个copy方法,问题倒是再也没有出现过。 

昨天老板同学又遇到这个问题,File#renameTo(File)方法在windows下面工作的好好的,在linux下偶尔又失灵了。回到家我扫了一遍JDK中File#renameTo(File)方法的源代码,发现它调用的是一个本地的方法(native method),无法再跟踪下去。网上有人说该方法在window下是正常的,在linux下面是不正常的。这个很难说通,SUN不可能搞出这种平台不一致的代码出来啊。 

后面在SUN的官方论坛上看到有人提到这个问题“works on windows, don't work on linux”,后面有人回复说是“file systems”不一样。究竟怎么不一样呢?还是没有想出来... 

后面在一个论坛里面发现了某人关于这个问题的阐述: 

引用
In the Unix'esque O/S's you cannot renameTo() across file systems. This behavior is different than the Unix "mv" command. When crossing file systems mv does a copy and delete which is what you'll have to do if this is the case.  

The same thing would happen on Windows if you tried to renameTo a different drive, i.e. C: -> D:



终于明白咯。 

做个实验: 

Java代码    收藏代码
  1. File sourceFile = new File("c:/test.txt");  
  2. File targetFile1 = new File("e:/test.txt");  
  3. File targetFile2 = new File("d:/test.txt");  
  4. System.out.println("source file is exist? " + sourceFile.exists()  
  5.     + ", source file => " + sourceFile);  
  6. System.out.println(targetFile1 + " is exist? " + targetFile1.exists());  
  7. System.out.println("rename to " + targetFile1 + " => "  
  8.     + sourceFile.renameTo(targetFile1));  
  9. System.out.println("source file is exist? " + sourceFile.exists()  
  10.     + ", source file => " + sourceFile);  
  11. System.out.println(targetFile2 + " is exist? " + targetFile2.exists());  
  12. System.out.println("rename to " + targetFile2 + " => "  
  13.     + sourceFile.renameTo(targetFile2));  



结果: 

Java代码    收藏代码
  1. source file is exist? true, source file => c:\test.txt  
  2. e:\test.txt is exist? false  
  3. rename to e:\test.txt => false  
  4. source file is exist? true, source file => c:\test.txt  
  5. d:\test.txt is exist? false  
  6. rename to d:\test.txt => true  



注意看结果,从C盘到E盘失败了,从C盘到D盘成功了。因为我的电脑C、D两个盘是NTFS格式的,而E盘是FAT32格式的。所以从C到E就是上面文章所说的"file systems"不一样。从C到D由于同是NTFS分区,所以不存在这个问题,当然就成功了。 

果然是不能把File#renameTo(File)当作move方法使用。 

可以考虑使用apache组织的commons-io包里面的FileUtils#copyFile(File,File)和FileUtils#copyFileToDirectory(File,File)方法实现copy的效果。至于删除嘛,我想如果要求不是那么精确,可以调用File#deleteOnExit()方法,在虚拟机终止的时候,删除掉这个目录或文件。 

BTW:File是文件和目录路径名的抽象表示形式,所以有可能是目录,千万小心。

 

 

下面原文地址:http://lvxiaoxi.iteye.com/blog/1868440

在使用compass 时,发现重建索引重命名文件失败,看了源码,原来源码用了 File renameTo的方法,于是自己做了试验,结合网上一位朋友的帖子  
http://xiaoych.iteye.com/blog/149328  
下面看我的测试:  
Java代码    收藏代码
  1.              boolean renamed = false;  
  2. File renameToIndexPathFile;  
  3. String path = "D:/apache-tomcat-7.0.6/webapps/cc/index/advertset";  
  4. File indexPathFile = new File(path);  
  5. int count = 1;  
  6. renameToIndexPathFile = new File(path + "-copy" + (count++));   
  7. renamed = indexPathFile.renameTo(renameToIndexPathFile);           
  8. System.out.println(renamed);  


如果把上面代码的path 间隔符改成下面就成功了:  
Java代码    收藏代码
  1. String path = "D:\\apache-tomcat-7.0.6\\webapps\\cc\\index\\advertset";  

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
批量重命名软件(VC6) 2019年03月30日 18:25:36 南棱笑笑生 阅读数:4 编辑 有时候需要批量重命名一整个目录的文件,一个一个的修改肯定花时间和精力了! https://item.jd.com/42982472342.html 基本信息 书名:Visual C++开发实战宝典(配光盘)(软件开发实战宝典) 定价:79.80元 作者:宋坤 等编著 出版社:清华大学出版社 出版日期:2009-12-01 ISBN:9787302209058 字数: 页码: 版次: 装帧:平装 开本:16开 商品重量: 可能宋坤先生默默无名,从里面还是找到了一个有用的程序,比如第8章的: 8.7 实战 8.7.2 对位图文件进行批量编号命名..............348 例8.12 目录名:FileRename 由于VC6早已经遭到淘汰了,但是联系编程还有稍许价值,现阶段只能在虚拟机VMware14中运行WINDOWS XP来安装运行VC6了。 还有一个重要的问题是360杀毒软件会将你编译生成的EXE文件都处理为未知的可疑文件,提醒你隔离或者删除!^_ 在360的老板周鸿祎的眼里草木皆兵:宁可错杀一千,不可放走一个! 为了简单期间,我将360杀毒和360安全卫士都退出了! 发现未知程序将要运行,是否放行? 可能是没有数字签名,微软的比尔盖茨也告诉你的程序不安全:^_ 无法验证发布者。您确定要运行此软件吗? 由于是为重命名BMP扩展名的位图文件准备的程序,因此程序运行的时候除了:E:\刘杨-商业修图教程 目录多了一个BMP目录之外啥也没有。(前缀使用:刘杨-商业修图教程。下同) 首先干掉必须是BMP扩展名! //开始批量重命名文件 void CFileRenameDlg::OnBtStart() { CFileFind flFind; CString szDir; m_FileDir.GetWindowText(szDir); flFind.FindFile(szDir + "\\*.*"); //统计位图数量 int nBmpCount = 0; CFileFind flFindCount; flFindCount.FindFile(szDir + "\\*.*"); while (flFindCount.FindNextFile()) { if (!flFindCount.IsDirectory()) { CString szPath; szPath = flFindCount.GetFilePath(); char szLetter[128] = {0}; //盘符 char szCurDir[128] = {0}; //目录 char szName[128] = {0}; //文件名 char szExt[128] = {0}; //扩展名 _splitpath(szPath.GetBuffer(0), szLetter, szCurDir, szName, szExt); //分解目录 //判断文件扩展名 //if (strcmp(szExt, ".bmp") == 0) { nBmpCount++; } } } flFindCount.Close(); m_Progress.SetRange32(0, nBmpCount); //遍历位图文件 szDir = szDir + "\\bmp"; CreateDirectory(szDir, NULL); //创建目录 int nIndex = 1; while(flFind.FindNextFile()) { if (!flFind.IsDirectory()) { CString szPath; szPath = flFind.GetFilePath(); char szLetter[128] = {0}; //盘符 char szCurDir[128] = {0}; //目录 char szName[128] = {0}; //文件名 char szExt[128] = {0}; //扩展名 _splitpath(szPath.GetBuffer(0), szLetter, szCurDir, szName, szExt); //分解目录 //获取前缀 CString szPrefix; m_Prefix.GetWindowText(szPrefix); //判断文件扩展名 //if (strcmp(szExt, ".bmp") == 0) { CFile file; CString szCreatedName = szDir; szCreatedName += "\\"; szCreatedName += szPrefix; //添加前缀 CString szIndex; szIndex.Format("%d", nIndex); szCreatedName += szIndex; //添加序号 szCreatedName += ".bmp"; m_Progress.SetPos(nIndex); nIndex++; //创建新的文件 file.Open(szCreatedName, CFile::modeCreate|CFile::modeReadWrite); CFile readFile; readFile.Open(szPath, CFile::modeRead); DWORD dwLen = readFile.GetLength(); BYTE *pData = new BYTE[dwLen]; readFile.ReadHuge((void*)pData, dwLen); readFile.Close(); file.WriteHuge((void*)pData, dwLen); file.Close(); delete [] pData; szCreatedName.ReleaseBuffer(); szIndex.ReleaseBuffer(); } } } flFind.Close(); CString szBmpCount; szBmpCount.Format("%d个文件!", nBmpCount); MessageBox("操作完成,处理" + szBmpCount); szBmpCount.ReleaseBuffer(); } 生成的文件名为: 刘杨-商业修图教程1.bmp 刘杨-商业修图教程10.bmp 刘杨-商业修图教程2.bmp 刘杨-商业修图教程3.bmp 刘杨-商业修图教程4.bmp 刘杨-商业修图教程5.bmp 刘杨-商业修图教程6.bmp 刘杨-商业修图教程7.bmp 刘杨-商业修图教程8.bmp 刘杨-商业修图教程9.bmp 还是需要修改扩展名: //开始批量重命名文件 void CFileRenameDlg::OnBtStart() { CFileFind flFind; CString szDir; m_FileDir.GetWindowText(szDir); flFind.FindFile(szDir + "\\*.*"); //统计位图数量 int nBmpCount = 0; CFileFind flFindCount; flFindCount.FindFile(szDir + "\\*.*"); while (flFindCount.FindNextFile()) { if (!flFindCount.IsDirectory()) { CString szPath; szPath = flFindCount.GetFilePath(); char szLetter[128] = {0}; //盘符 char szCurDir[128] = {0}; //目录 char szName[128] = {0}; //文件名 char szExt[128] = {0}; //扩展名 _splitpath(szPath.GetBuffer(0), szLetter, szCurDir, szName, szExt); //分解目录 //判断文件扩展名 //if (strcmp(szExt, ".bmp") == 0) { nBmpCount++; } } } flFindCount.Close(); m_Progress.SetRange32(0, nBmpCount); //遍历位图文件 szDir = szDir + "\\bmp"; CreateDirectory(szDir, NULL); //创建目录 int nIndex = 1; while(flFind.FindNextFile()) { if (!flFind.IsDirectory()) { CString szPath; szPath = flFind.GetFilePath(); char szLetter[128] = {0}; //盘符 char szCurDir[128] = {0}; //目录 char szName[128] = {0}; //文件名 char szExt[128] = {0}; //扩展名 _splitpath(szPath.GetBuffer(0), szLetter, szCurDir, szName, szExt); //分解目录 //获取前缀 CString szPrefix; m_Prefix.GetWindowText(szPrefix); //判断文件扩展名 //if (strcmp(szExt, ".bmp") == 0) { CFile file; CString szCreatedName = szDir; szCreatedName += "\\"; szCreatedName += szPrefix; //添加前缀 CString szIndex; szIndex.Format("%d", nIndex); szCreatedName += szIndex; //添加序号 //szCreatedName += ".bmp"; szCreatedName += szExt; m_Progress.SetPos(nIndex); nIndex++; //创建新的文件 file.Open(szCreatedName, CFile::modeCreate|CFile::modeReadWrite); CFile readFile; readFile.Open(szPath, CFile::modeRead); DWORD dwLen = readFile.GetLength(); BYTE *pData = new BYTE[dwLen]; readFile.ReadHuge((void*)pData, dwLen); readFile.Close(); file.WriteHuge((void*)pData, dwLen); file.Close(); delete [] pData; szCreatedName.ReleaseBuffer(); szIndex.ReleaseBuffer(); } } } flFind.Close(); CString szBmpCount; szBmpCount.Format("%d个文件!", nBmpCount); MessageBox("操作完成,处理" + szBmpCount); szBmpCount.ReleaseBuffer(); } 得到的文件名为: 刘杨-商业修图教程1.avi 刘杨-商业修图教程10.avi 刘杨-商业修图教程2.avi 刘杨-商业修图教程3.avi 刘杨-商业修图教程4.avi 刘杨-商业修图教程5.avi 刘杨-商业修图教程6.avi 刘杨-商业修图教程7.avi 刘杨-商业修图教程8.avi 刘杨-商业修图教程9.avi 现在你就会发现你所命名的文件一位数和两位数的掺杂在一起,不整洁! 假定你所批量命名的文件名不超过100个(最多99个。) 继续修改代码: 刘杨-商业修图教程01.avi 刘杨-商业修图教程02.avi 刘杨-商业修图教程03.avi 刘杨-商业修图教程04.avi 刘杨-商业修图教程05.avi 刘杨-商业修图教程06.avi 刘杨-商业修图教程07.avi 刘杨-商业修图教程08.avi 刘杨-商业修图教程09.avi 刘杨-商业修图教程10.avi 结束语: 本程序还可以继续修改,改名之前直接统计需要重命名的文件的数目,然后自动配置一位数、二位数、三位数等等。 可能是微软的比尔盖茨的原因,最后重命名的文件的计数有点问题。不影响工作!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值