转载地址: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:

终于明白咯。

做个实验:

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

请慎用java的File#renameTo(File)方法的更多相关文章

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

    以前我一直以为File#renameTo(File)方法与OS下面的 move/mv 命令是相同的,可以达到改名.移动文件的目的.不过后来经常发现问题:File#renameTo(File)方法会返回 ...

  2. 在java中使用 File.renameTo(File)实现重命名.

    Here is part of my files: [北京圣思园Java培训教学视频]Java.SE.前9日学习成果测试题(2010年12月2日).rar [北京圣思园Java培训教学视频]Java. ...

  3. Java中File常用的方法汇总

    创建:createNewFile()在指定位置创建一个空文件,成功就返回true,如果已存在就不创建,然后返回false.mkdir() 在指定位置创建一个单级文件夹.mkdirs() 在指定位置创建 ...

  4. java基础学习日志---File方法分析

    package FunDemo; import java.io.File; import java.io.IOException; import java.util.Arrays; public cl ...

  5. Java编程思想:File类其他方法

    import java.io.File; public class Test { public static void main(String[] args) { MakeDirectories.te ...

  6. 【转】Java中File常用的方法汇总

    创建:createNewFile()在指定位置创建一个空文件,成功就返回true,如果已存在就不创建,然后返回false.mkdir() 在指定位置创建一个单级文件夹.mkdirs() 在指定位置创建 ...

  7. Java中File类的方法详解

    File类也是Java中一个比较重要的类,通过他我们可以实现对文件的一系列操作,其内置了很多方法,下面我将按方法的功能分块,逐一讲解: 快速导航 构造方法 常用方法 创建目录 判断 `is...` t ...

  8. java之io之File类的list()方法过滤目录的使用

    java的io的知识中,File类必须掌握.File类是对文件或者文件夹的封装.它本身并不能对所封装的文件进行读写,它封装的只是文件或文件夹的周边知识,比如 大小啦,创建日期啦,路径啦等等. 如果Fi ...

  9. Java文件操作二:File文件的方法

    一.文件的判断方法 判断方法 .boolean canExecute()判断文件是否可执行 .boolean canRead()判断文件是否可读 .boolean canWrite() 判断文件是否可 ...

随机推荐

  1. Leetcode 15. 3Sum

    Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all un ...

  2. Linux下如何查找.sh后缀的文件

    find / -name *.sh或locate *.shfind 与locate的区别:locate 配合数据库查看文件位置 find 实际搜寻硬盘查询文件名称

  3. 个人CKeditor的config.js配置

    /** * @license Copyright (c) 2003-2016, CKSource - Frederico Knabben. All rights reserved. * For lic ...

  4. 认真研究一下Gradients css3(无聊笔记)(原)

    渐变(gradients)分为2种: 线性渐变(Linear Gradients)- 向下/向上/向左/向右/对角方向 径向渐变(Radial Gradients)- 由它们的中心定义 红色框表示可重 ...

  5. History lives on in this distinguished Polish city II 2017/1/5

    原文 Some fresh air After your time underground,you can return to ground level or maybe even a little ...

  6. window.onload 和 DOMContentLoaded区别及如何判断dom是否加载完毕

    http://blog.allenm.me/2010/02/window-onload-和-domcontentloaded/ 其中使用IE不支持DOMContentLoaded,那么判断IE是否加载 ...

  7. RF Firefox Profile

    默认情况下,robot framework是启动不带任何配置信息的firefox,如果需要启动带有profile的话,增加一个参数即可,如 Open Browser https://aws-qa5.i ...

  8. 12月15日下午Smarty模板函数

    1.{$var=...} 这是{assign}函数的简写版,你可以直接赋值给模版,也可以为数组元素赋值. <{$a = 10}><!--赋值语句--> <{$a}> ...

  9. Linux学习笔记<六>

    进程与程序 1.子程序与父程序 PID是进程的ID,PPID是其父进程的ID 登录bash之后,就是获取了一个名为bash的PID,在这个环境上所执行的其他命令,就是其子程序 common@commo ...

  10. 【辅助远程连接,可穿防火墙、NAT】一次 TeamViewer 的安装与测试

    背景: 应课程老师要求帮助某化学老师维修机器(高性能电脑),并解决老师的若干问题,在解决硬件问题(上网问题:多个网络接口)之后,化学老师提出需要远程链接到该机器,试询问之前如何实现,化学老师推荐Tea ...