java 中File方法reNameTo时老是返回false,总是返回false解决办法
(2012-04-11 14:39:22)
标签:
javafile方法renameto老是返回false总是返回false解决办法杂谈 |
分类: 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”不一样。究竟怎么不一样呢?还是没有想出来...
后面在一个论坛里面发现了某人关于这个问题的阐述:
终于明白咯。
做个实验:
结果:
昨天老板同学又遇到这个问题,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:
The same thing would happen on Windows if you tried to renameTo a different drive, i.e. C: -> D:
终于明白咯。
做个实验:
1
2
3
4
5
6
7
8
9
|
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)); |
结果:
1
2
3
4
5
6
|
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是文件和目录路径名的抽象表示形式,所以有可能是目录,千万小心。