以前我一直以为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是文件和目录路径名的抽象表示形式,所以有可能是目录,千万小心。

文件系统不一样好像是说 windows和Linux的文件默认为NTFS的 而Linux是ext32的

在大压力情况下在windows renameTo有一定概率失败的情况。
在linux操作系统上在不同盘符之间renameTo也会失败。典型的应用场景就是从本地硬盘renameTo到mount的硬盘上或文件系统上。

copy文件尽量使用FileUtilsc.opyFileToDirectory(File,File)

还有个问题是在使用webwork的fileUpload拦截器的时候尽量不要使用execAndWait拦截器,两个拦截器会开启两个线程,很可能会删掉还没有处理的临时上传文件文件而导致文件找不到。

http://xiaoych.iteye.com/blog/149328

最新文章

  1. [译]ES6箭头函数和它的作用域
  2. 土豪聪要请客(stol)
  3. 浏览器内置Console函数使用详解
  4. AngularJs练习Demo18 Resource
  5. HDU 4415 - Assassin’s Creed
  6. 虚拟环境管理工具virtualenvwrapper-win初试
  7. 基于visual Studio2013解决C语言竞赛题之1061最大值和次最大值
  8. RealThinClient学习(一)
  9. ubuntu下安装BeyondCompare比较工具
  10. rabbitmq安装Management Plugin
  11. 基于redis实现tomcat8及以上版本的tomcat集群的session持久化实现(tomcat-redis-session-manager二次开发)
  12. HDU 6184 Counting Stars 经典三元环计数
  13. Android ADB Server启动失败
  14. 使用Angular CLI从蓝本生成代码
  15. Java-每日编程练习题②(数组练习)
  16. DocumentEvent事件的应用
  17. python os.walk()遍历文件夹
  18. ubuntu16.04 登陆不进桌面
  19. Teradata的profile使用
  20. ProcessHacker可编译版本

热门文章

  1. Hibernate 多对多映射
  2. Linux服务器使用SSH的命令(有详细的参数解释)
  3. Ultra Office Control 2.0
  4. perl 处理perl返回的json
  5. poj 3263 Tallest Cow
  6. java.lang.ClassNotFoundException: org.apache.catalina.loader.DevLoader
  7. 事务管理在三层架构中应用以及使用ThreadLocal再次重构
  8. MVC控制器里面使用dynamic和ExpandoObject
  9. guava之Joiner 和 Splitter(转)
  10. 在Centos 5.4上安装Mysql5.5.10 (整理以前的工作文档)