`
xiaoych
  • 浏览: 144974 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

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

    博客分类:
  • java
阅读更多
以前我一直以为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:


终于明白咯。

做个实验:


File sourceFile = new File("c:/test.txt");
File targetFile1 = new File("e:/test.txt");
File targetFile2 = new File("d:/test.txt");
System.out.println("source file is exist? " + sourceFile.exists()
    + ", source file => " + sourceFile);
System.out.println(targetFile1 + " is exist? " + targetFile1.exists());
System.out.println("rename to " + targetFile1 + " => "
    + sourceFile.renameTo(targetFile1));
System.out.println("source file is exist? " + sourceFile.exists()
    + ", source file => " + sourceFile);
System.out.println(targetFile2 + " is exist? " + targetFile2.exists());
System.out.println("rename to " + targetFile2 + " => "
    + sourceFile.renameTo(targetFile2));


结果:


source file is exist? true, source file => c:\test.txt
e:\test.txt is exist? false
rename to e:\test.txt => false
source file is exist? true, source file => c:\test.txt
d:\test.txt is exist? false
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是文件和目录路径名的抽象表示形式,所以有可能是目录,千万小心。
分享到:
评论
16 楼 何飞同学要加油 2014-12-18  
文件系统不一样好像是说 windows和Linux的文件默认为NTFS的 而Linux是ext32的
15 楼 lvxiaoxi 2013-05-14  
还有一种情况,看我的博文:
http://lvxiaoxi.iteye.com/blog/1868440
14 楼 di1984HIT 2013-02-05  
嗯,说的很对啊。
13 楼 xxm7801877 2013-01-05  
                   
12 楼 clican 2008-07-28  
我还碰到过在大压力情况下在windows renameTo有一定概率失败的情况。
在linux操作系统上在不同盘符之间renameTo也会失败。典型的应用场景就是从本地硬盘renameTo到mount的硬盘上或文件系统上。
11 楼 xiaobai1023 2008-07-18  
有时候要注意对文件的引用是否已经关闭了
10 楼 cmoaciopm 2008-01-22  
jdk版本:1.5.0_09
操作系统:WindowsXP sp2
环境:C盘为NTFS分区,F盘为FAT32分区
现象:1.将C盘的文件renameTo到F盘,返回成功且文件移动成功
      2.将F盘的文件renameTo到C盘,返回成功且文件移动成功

并没有出现楼主所说的现象,不知道是不是jdk版本的问题
9 楼 温柔一刀 2008-01-21  
确实是这样的,曾经遇到过。copy文件尽量使用FileUtilsc.opyFileToDirectory(File,File)

还有个问题是在使用webwork的fileUpload拦截器的时候尽量不要使用execAndWait拦截器,两个拦截器会开启两个线程,很可能会删掉还没有处理的临时上传文件文件而导致文件找不到。
8 楼 zhanjianhua 2008-01-10  
File oldFile = new File(souceFile);
File newFile = new File(souceFile.replace(".", "del."));
oldFile.renameTo(newFile);
这样修改文件名,oldFile, newFile怎么关闭,没看到JDK中有这方面的方法?
还有这种修改文件名,无限制的修改下去,并且修改不同的文件名,会报java.io.IOException: java.io.IOException: Too many open files的错不
7 楼 Jonney 2007-12-22  
很久以前看过一本书介绍了java里面的很多个陷阱,
从此我一直把java.io.File当成是java.io.Filename来看待。
6 楼 linxizeng 2007-12-21  
就是喜欢这种实际经验的贴...
5 楼 xiaoych 2007-12-21  
zhangzhaofeng 写道
对楼主说的进行了在Windows下面的测试
我自己发现有3种情况会在
不同盘之间的copy中出错

第一:源文件不存在
第二:目标文件存在
第三:都不存在

楼主的那种rename to d:\test1.txt => false
我怀疑是第一种情况
应该和盘符没有关系


我改正了一下逻辑错误,多谢你的提醒,呵呵
4 楼 xiaoych 2007-12-21  
是的,File#renameTo(File)方法 有很多种情况会返回false或者抛出异常。我做的那个测试只是想表达其中的一种情况:

就是源文件存在,目标文件不存在,对目标目录有写入权限(由于是windows下面的administrator,所以默认会有),但是"file systems"不同,也会返回失败。

这是我们最需要注意的,也就是我写这个的原因。
3 楼 zhangzhaofeng 2007-12-21  
可能我的判断是有问题的
rename好奇怪
2 楼 zhangzhaofeng 2007-12-21  
对楼主说的进行了在Windows下面的测试
我自己发现有3种情况会在
不同盘之间的copy中出错

第一:源文件不存在
第二:目标文件存在
第三:都不存在

楼主的那种rename to d:\test1.txt => false
我怀疑是第一种情况
应该和盘符没有关系
1 楼 myreligion 2007-12-19  
如果目标文件已经存在,rename一般也会失败,返回false。这个东西还是很靠不住的,不知道实现者是怎么想的。

相关推荐

    Better File Rename 绿色汉化版

    Better File Rename 5.7 绿色汉化版 Better File Rename 是一款强大易用的文件批量改名软件。内置最全面的重命名选项。 现已支持64位操作系统。 5.7 英文原版更新说明: ① 添加了 PDF 格式的用户手册 ② 在所有...

    Better File Rename 好用的文件重命名工具

    Better File Rename 好用的文件重命名工具

    Better File Rename文件重命名工具

    Better File Rename文件重命名工具,功能强大,各种重命名。 适合文件处理各种使用。

    Better File Rename v5.7

    Better File Rename 是一款WINDOWS 资源管理器的扩展外壳,可以帮助你快速简便的修改文件名和文件修改时间,可以分别处理文件名和扩展名。

    Quick File Rename 1.2

    Quick File Rename 批量修改文件后缀,功能简单,但很实用。个人认为比那些体积庞大的工具要好用的多。

    java临时文件重命名-Java程序重命名文件或目录.pdf

    java临时⽂件重命名_Java程序重命名⽂件或⽬录 ⽅法java.io.File.renameTo()⽤于重命名⽂件或⽬录。此⽅法需要⼀个参数,即⽂件或⽬录被重命名的名称,重命名成功后返回true,否则 返回false。 演⽰此的程序如下所⽰...

    Better File Rename 4.9.4

    是一款WINDOWS资源管理器的扩展外壳,可以帮助你快速简便的修改文件名和文件修改时间,可以分别处理文件名和扩展名。 一款WINDOWS资源管理器的扩展外壳, 可以帮助你快速简便地修改文件名和文件修改时间。...

    FileNameChanger_RenameFile_

    XML file to rename bulk of files

    Delphi RenameFile修改文件名范例.rar

    本例中修改文件名使用Delphi中自带函数RenameFile来实现,具体用法可参考下述代码:  Try  RenameFile(Edit1.Text,Edit2.Text);  SHowMessage('更改成功');  except  ShowMessage('更改失败');  end;

    rename file

    该程序可以成批次的更改文件名称,代码值得学习研究,编译后,即可执行

    file_rename.zip

    python笔记源码,凑字数:请支持我请支持我请支持我请支持我

    rename_file_v1.1.zip

    基于上一个版本修正: 1、正则修正忽略大小写,支持E/EP/Ep/e/ep/eP等 2、支持百集以上电视剧,并自动在单数补0,如100集电视剧,第一集表示为001

    plan_in_GitHub365

    GitHub365计划 此举主要目的是为了复习以前的知识,并对自己的自律进行...RenameMess.java 测试 renameTo 重命名方法 ####2015-1-26 BulbbleSort.java 冒泡排序 ####2015-1-27 duotaiarray-* 多态数组的demo ####2015-

    Better File Rename 个人珍藏 批量文件重命名利器

    本不该要分 但我下载缺分 没办法,大家多支持逸云科技!谢谢 一款WINDOWS资源管理器的扩展外壳, 可以帮助你快速简便地修改文件名和文件修改时间。功能有:强大的命名方式,文字、日期和序列数字的添加、去除、插入和...

    FILE_fopen_rename_file_

    这是一个打开文件实例,讲述了几个文件函数以及字符串函数的用法,有点乱

    Better File Rename

    批量重命名 綠色 file rename

    Ben's_File3576422019_hitngm_RenameFile_seldomxyk_

    File Reamer is a small program to allow you to rename multiple files. You may need this program if you need to rename lots of pictures e.g. from a camera

    解决log4j:ERROR Failed to rename代码包

    log4j:ERROR Failed to rename错误解决办法 http://www.blogjava.net/DreamAngel/archive/2011/11/10/363400.html

Global site tag (gtag.js) - Google Analytics