Java Android中file.renameTo(文件)会出什么问题

Java Android中file.renameTo(文件)会出什么问题,java,android,file,file-io,file-rename,Java,Android,File,File Io,File Rename,我正在阅读的File.class中的renameTo(File)文档 我们在生产中使用这种方法已经有一段时间了,但我一直在想可能会出现什么问题。文件上说 将此文件重命名为newPath。文件和目录都支持此操作 许多失败是可能的。一些更可能的故障包括: 在包含源路径和目标路径的目录上需要写入权限 两条路径的所有父级都需要搜索权限 两条路径必须位于同一装载点上。在Android上,应用程序是最重要的 尝试在之间复制时可能会达到此限制 内部存储器和SD卡。请注意,此方法不会抛出 失败时出现异常。调用

我正在阅读的
File.class
中的
renameTo(File)
文档

我们在生产中使用这种方法已经有一段时间了,但我一直在想可能会出现什么问题。文件上说

将此文件重命名为newPath。文件和目录都支持此操作

许多失败是可能的。一些更可能的故障包括:

  • 在包含源路径和目标路径的目录上需要写入权限

  • 两条路径的所有父级都需要搜索权限

  • 两条路径必须位于同一装载点上。在Android上,应用程序是最重要的 尝试在之间复制时可能会达到此限制 内部存储器和SD卡。请注意,此方法不会抛出 失败时出现异常。调用者必须检查返回值


renameTo()
可能失败的原因还有哪些(指更可能的失败)?调用
renameTo
后是否有保证状态?当
renameTo()
失败时,我能指望保留原始文件吗?我想检查uber的任何其他条件,以确保它与文档中描述的条件一起工作?

在Android文件中。rename调用Linux rename()(通过libcore)。您可以查看可能出现的故障列表,在Linux上可能略有不同,但应该能让您大致了解情况

还请注意这一说法:

如果rename()函数因[EIO]以外的任何原因失败,则由new命名的任何文件均不受影响


列出的三个是更可能发生的故障。不太可能(但可能!)的失败包括

  • 用户错误(例如,源是文件,目标是现有目录,反之亦然)
  • 设备上没有剩余空间
  • 文件系统安装的只读
  • 损坏的文件系统
  • 旋转磁盘上的坏扇区
由于Android是基于Linux的,所以您可能可以依靠以下几点:

  • 如果重命名失败,两个文件将保持原样
  • 如果目标文件存在,并且重命名成功,任何进程都不会发现目标文件丢失(替换是原子的)

由于我不知道的原因,无法使用file.rename()在Android中将文件移动到不同的挂载目录(如sdcard0和sdcard1),以下是我的解决方案,它适合我:

if(canRename(f1, f2)) {
    if(!f1.renameTo(f2)) {
        Log.e(TAG, "Error to move new app: " + f1 + " > " + f2);
    }
} else {
    try {
        copy(f1, f2);
        f1.delete();
    } catch (Exception ex) {
        Log.e(TAG, "Error to move new app: " + f1 + " > " + f2);
    }
}

private void copy(final File f1, final File f2) throws IOException {
    f2.createNewFile();

    final RandomAccessFile file1 = new RandomAccessFile(f1, "r");
    final RandomAccessFile file2 = new RandomAccessFile(f2, "rw");

    file2.getChannel().write(file1.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, f1.length()));

    file1.close();
    file2.close();
}

private boolean canRename(final File f1, final File f2) {
    final String p1 = f1.getAbsolutePath().replaceAll("^(/mnt/|/)", "");
    final String p2 = f2.getAbsolutePath().replaceAll("^(/mnt/|/)", "");

    return p1.replaceAll("\\/\\w+", "").equals(p2.replaceAll("\\/\\w+", ""));
}

非常感谢。从文档中可以清楚地看到,重命名在不同的装载点之间不起作用。这个问题的目的是了解还有什么地方会出错。@user1079877我已经用你的代码在broadcastreceiver上重命名了图像,它工作得很好,直到android 6在运行时检查了权限,所以现在f2.createNewFile();提出访问被拒绝的例外情况,您有任何报价吗?