如何为失败的Java File对象调用获取有意义的消息(mkdir,rename,delete)

And*_*ite 14 java filesystems

在使用File.mkdir和朋友时,我注意到他们不会在失败时抛出异常!值得庆幸的是FindBugs指出了这一点,现在我的代码至少检查了返回值,但我仍然看不到有关调用失败原因的有意义信息!

如何找出调用这些File方法失败的原因?是否有一个很好的替代品或库来处理这个问题?

我已经在SO和Google上进行了一些搜索,并发现了关于此主题的令人惊讶的小信息.

[更新]我试过VFS,它的例外没有任何有用的信息.例如,尝试移动最近删除的目录导致Could not rename file "D:\path\to\fileA" to "file:///D:/path/do/fileB".无法提及fileA不再存在.

[更新]业务要求仅限于JDK 1.6解决方案,因此JDK 1.7已经淘汰

sbr*_*ges 9

您可以调用本机方法,并以这种方式获取正确的错误代码.例如,c函数 mkdir具有错误代码,如EEXIST和ENOSPC.您可以使用JNA轻松访问这些本机函数.如果您支持*nix和windows,则需要创建此代码的两个版本.

有关Linux上的jna mkdir的示例,您可以这样做,

import java.io.IOException;

import com.sun.jna.LastErrorException;
import com.sun.jna.Native;

public class FileUtils {

  private static final int EACCES = 13;
  private static final int EEXIST = 17;
  private static final int EMLINK = 31;
  private static final int EROFS = 30;
  private static final int ENOSPC = 28;
  private static final int ENAMETOOLONG = 63;

  static void mkdir(String path) throws IOException {

    try {
      NativeLinkFileUtils.mkdir(path);

    } catch (LastErrorException e) {
      int errno = e.getErrorCode();
      if (errno == EACCES)
        throw new IOException(
            "Write permission is denied for the parent directory in which the new directory is to be added.");
      if (errno == EEXIST)
        throw new IOException("A file named " + path + " already exists.");
      if (errno == EMLINK)
        throw new IOException(
            "The parent directory has too many links (entries).  Well-designed file systems never report this error, because they permit more links than your disk could possibly hold. However, you must still take account of the possibility of this error, as it could result from network access to a file system on another machine.");
      if (errno == ENOSPC)
        throw new IOException(
            "The file system doesn't have enough room to create the new directory.");
      if (errno == EROFS)
        throw new IOException(
            "The parent directory of the directory being created is on a read-only file system and cannot be modified.");
      if (errno == EACCES)
        throw new IOException(
            "The process does not have search permission for a directory component of the file name.");
      if (errno == ENAMETOOLONG)
        throw new IOException(
            "This error is used when either the total length of a file name is greater than PATH_MAX, or when an individual file name component has a length greater than NAME_MAX. See section 31.6 Limits on File System Capacity.");
      else
        throw new IOException("unknown error:" + errno);
    }




  }
}

class NativeLinkFileUtils {
  static {
    try {
      Native.register("c");
    } catch (Exception e) {
      e.printStackTrace();
    }
  }

  static native int mkdir(String dir) throws LastErrorException;

}
Run Code Online (Sandbox Code Playgroud)


Mar*_*aux 5

您可以使用以下内容创建实用程序类:

public int mkdir(File dirToCreate) throws IOException
{
    if (dirToCreate.exists())
        throw new IOException("Folder already exists");

    if (!dirToCreate.getParent().canWrite())
        throw new IOException("No write access to create the folder");

    return dirToCreate.mkdir();
}


public int rename(File from, File to) throws IOException, FileNotFoundException
{
    if (from.equals(to))
        throw new IllegalArgumentException("Files are equal");

    if (!from.exists())
        throw new FileNotFoundException(from.getAbsolutePath() + " is not found");

    if (!to.getParent().exists())
        throw new IllegalAccessException("Parent of the destination doesn't exist");

    if (!to.getParent().canWrite())
        throw new IllegalAccessException("No write access to move the file/folder");

    return from.renameTo(to);
}
Run Code Online (Sandbox Code Playgroud)

当然这还不完整,但你可以解决这个问题.

  • 这种方法也充满了竞争条件. (4认同)
  • 看起来可能但是可能很难获得"正确".有很多可能性来测试底层系统应该"知道".例如,检测到mkdir om网络路径因网络错误而失败. (3认同)
  • 并且这些测试都不是原子的,就像文件系统上的操作会报告一样.例如,文件夹可以由`.exists()`和`.mkdir()`之间的另一个进程创建. (3认同)
  • 如果磁盘已满,会发生什么? (2认同)

Rya*_*art 5

使用JDK7的新文件API.它有更好的操作系统集成,并提供更详细的反馈.例如,请参阅移动/重命名文档.