以前我一直以为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:

终于明白咯。

做个实验:

  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));

结果:

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

最新文章

  1. js中this的绑定
  2. Linux系统性能分析
  3. Java中static的理解
  4. 《zw版·Halcon-delphi系列原创教程》 Halcon分类函数008,matrix,矩阵函数
  5. Windows Sockets Error Codes
  6. 实体框架Entity Framework 4.1快速入门
  7. Bzoj 1984: 月下“毛景树” 树链剖分
  8. 团队作业6——展示博客(Alpha版本)
  9. 【ASP.NET MVC 学习笔记】- 11 Controller和Action(2)
  10. C语言中函数可变参数解析
  11. R语言学习 第八篇:常用的数据处理函数
  12. 阅读nsq源码 ---初步架构设计图
  13. 视觉显著性简介 Saliency Detection
  14. jQuery ajax解析xml文件demo
  15. sublime3安装ctags追踪插件
  16. VB6 加密解密字符串
  17. 2016-2017-2 20155312 实验四Android程序设计实验报告
  18. RHEL6.5安装multipath多路径软件
  19. 3 个简单、优秀的 Linux 网络监视器
  20. spring study

热门文章

  1. myeclipse重新添加spring支持
  2. vscode 自定义快捷键
  3. WebService系列一:WebService简介
  4. Linux--nginx域名绑定-url rewrite
  5. FastFel解析一个公式的步骤
  6. glsl boom
  7. git忽略已添加版本控制的文件
  8. windows使用技巧和工具(后面可能更新linux)
  9. spark 分析日志文件(key,value)
  10. 原来找字也可以这样用ElseIf FindStr 手机按键精灵 跟大漠的区别