java mv file_从java重命名文件失败来看mv的内部实现过程

下面是一个调用java的文件重命名方法的小程序:

importjava.io.*;

publicclassFileRenameTest

{

publicstaticvoidmain(String[] args)

{

if(args.length<2)

{

System.out.println("Usage:java FileRenameTest  ");

return;

}

System.out.println("prepare to renaming file["+args[0]+"] to file["+args[1]+"]");

booleanstatus=newFile(args[0]).renameTo(newFile(args[1]));

System.out.println("status:"+String.valueOf(status));

}

}

在aix5.1或rhel6.1上准备把一个文件重命名到另一个文件系统中。最终执行的结果都是不能成功。

为什么通过系统命令mv却可以成功把一个文件重命名到另一个设备中呢?

在aix通过下列命令来观察此java程序执行过程系统内部的处理过程。

truss -f -o rename.aix.truss java -cp . FileRenameTest origin.txt /tmp/origin.txt

在输出文件中找到下列重要信息。

8486994: 5308421: kwrite(1, " p r e p a r e   t o   r".., 61) = 61

8486994: 5308421: kwrite(1, "\n", 1)            = 1

8486994: 5308421: rename("origin.txt", "/tmp/origin.txt") Err#18 EXDEV

8486994: 5308421: kwrite(1, " s t a t u s : f a l s e", 12) = 12

8486994: 5308421: kwrite(1, "\n", 1)            = 1

从上面的内容可以看系统调用rename执行的结果是失败。Errno是18,也就是EXDEV错误。

在rhel6.1通过下列命令来观察此java程序执行过程系统内部的处理过程。

strace -fxo rename.rh.strace java -cp . FileRenameTest origin.txt /tmp/origin.txt

在输出文件中可以找到下列重要信息。

19517 write(1,"prepare to renaming file[origin."..., 61) = 61

19517 write(1,"\n", 1)                 = 1

19517 rename("origin.txt","/tmp/origin.txt") = -1 EXDEV (Invalidcross-device link)

19517 write(1,"status:false", 12)      = 12

19517 write(1,"\n", 1)                 = 1

失败的原因与aix上失败的原因是一致的,都是非法的跨设备的操作。

我们来观察一下在aix及rhel上mv命令的执行过程。

通过下列命令来观察aix上mv的执行过程

truss -f -o mv.aix.truss mv origin.txt /tmp/origin.txt

输出文件中可以看到下列重要信息。

6283516: 10338403: statx("origin.txt", 0x2FF22570, 176, 021) = 0

6283516: 10338403: statx("/tmp/origin.txt", 0x2FF22620, 176, 021) Err#2  ENOENT

6283516: 10338403: access("/tmp/origin.txt", 0)     Err#2  ENOENT

6283516: 10338403: rename("origin.txt","/tmp/origin.txt") Err#18 EXDEV

6283516: 10338403: statx("origin.txt", 0x2FF22570, 176, 021) = 0

6283516: 10338403:open("origin.txt", O_RDONLY|O_LARGEFILE) = 3

6283516: 10338403: statx("/tmp/origin.txt", 0x2FF22198, 176, 020) Err#2  ENOENT

6283516: 10338403:open("/tmp/origin.txt", O_WRONLY|O_CREAT|O_TRUNC|O_LARGEFILE, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) = 4

6283516: 10338403: fstatx(3, 0x2FF22248, 176, 020)  = 0

6283516: 10338403: fstatx(4, 0x2FF222F8, 176, 020)  = 0

6283516: 10338403: fstatfs(4, 0x2FF22430)       = 0

6283516: 10338403: kread(3," w w w w w w w\n\0\0\0\0".., 4096) = 8

6283516: 10338403: kwrite(4," w w w w w w w\n", 8) = 8

6283516: 10338403: kread(3," w w w w w w w\n\0\0\0\0".., 4096) = 0

6283516: 10338403: statx("origin.txt", 0x2FF22038, 176, 020) = 0

6283516: 10338403: __statxacl("origin.txt", 0x0000000000000000, 0x00000000, 0x2FF22028, 0x30003D08, 0x2FF22010) = 0

6283516: 10338403: chown("/tmp/origin.txt", 212, 1) = 0

6283516: 10338403: chmod("/tmp/origin.txt", 0100644)    = 0

6283516: 10338403: __chxacl("/tmp/origin.txt", 0x0000000000000000, 0x0000000000000002, 0x41495843, 0, 06000036410) = 0

6283516: 10338403: listea("origin.txt","", 0)      Err#48 EFORMAT

6283516: 10338403:close(3)             = 0

6283516: 10338403:close(4)             = 0

6283516: 10338403: utimes("/tmp/origin.txt", 0x2FF22188)    = 0

6283516: 10338403: unlink("origin.txt")         = 0

mv命令执行过程大致如下:先调用rename,如果不成功则读原文件内容复制到新创建的目录文件中。再通过unlink取消原文件的链接数。如果原文件链接数为0,则会删除此文件。

在rhel上mv内部调用过程总体上与aix上是一致的。

不知道是基于什么原因考虑,java类库中renameTo方法的内部执行不与mv的执行保持一致。我觉得这是一个API实现上的瑕疵。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值