代码之家  ›  专栏  ›  技术社区  ›  Nathan

Files.createDirectories()抛出FileAlreadyExistsExceptions,但没有目录

  •  -1
  • Nathan  · 技术社区  · 7 年前

    This question 问了一个类似的问题。但是,在我的例子中,目录在调用之前或之后都不存在 Files.createDirectories() . 这发生在oraclejdk10.0.2上。

    这是我的密码。。。

    Set<PosixFilePermission> perms;
    FileAttribute<?> attr;
    Path path;
    File directory;
    
    directory = new File("/test/http/localhost_4452/UCF2b/Live");
    path      = directory.toPath();
    perms     = EnumSet.noneOf(PosixFilePermission.class);
    
    perms.add(PosixFilePermission.OWNER_READ);
    perms.add(PosixFilePermission.OWNER_WRITE);
    perms.add(PosixFilePermission.OWNER_EXECUTE);
    
    attr = PosixFilePermissions.asFileAttribute(perms);
    
    try
    {
       if (!directory.exists())
          Files.createDirectories(path, attr);
    }
    catch (IOException e)
    {
       if (!directory.exists())
       {
          ... collect more information about the state of the directory and its parent path ...
          ... add this information as a suppressed exception ...
          throw e;
       }
       // else do nothing and assume another thread created the directory
    }
    

    这是个例外。。。

    java.nio.file.FileAlreadyExistsException: /test/http/localhost_4452/UCF2b/Live
    at java.base/sun.nio.fs.UnixException.translateToIOException(UnixException.java:94)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:111)
    at java.base/sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:116)
    at java.base/sun.nio.fs.UnixFileSystemProvider.createDirectory(UnixFileSystemProvider.java:385)
    at java.base/java.nio.file.Files.createDirectory(Files.java:682)
    at java.base/java.nio.file.Files.createAndCheckIsDirectory(Files.java:789)
    at java.base/java.nio.file.Files.createDirectories(Files.java:735)
    at ...my code...
    

    当前用户是root。以下是收集的有关目录及其父目录的诊断信息。这些信息收集在 catch 如果目录不存在,则阻止。

    +--------------------------------------+--------+----------+--------------------------+---------+-----------+-------+--------+---------+-------+-------+
    |            Path                      | Exists |  Length  |        Modified          |  Owner  | Directory | File  | Hidden | Execute | Read  | Write |
    +--------------------------------------+--------+----------+--------------------------+---------+-----------+-------+--------+---------+-------+-------+
    | /test/http/localhost_4452/UCF2b/Live | false  |   0.00 B | 1970-01-01T00:00:00Z     | (null)  | false     | false | false  | false   | false | false |
    | /test/http/localhost_4452/UCF2b      | true   |  4.00 kB | 2018-11-04T20:32:09.769Z | root    | true      | false | false  | true    | true  | true  |
    | /test/http/localhost_4452            | true   |  4.00 kB | 2018-11-04T20:18:26.849Z | root    | true      | false | false  | true    | true  | true  |
    | /test/http                           | true   |  4.00 kB | 2018-11-04T20:11:42.605Z | root    | true      | false | false  | true    | true  | true  |
    | /test/                               | true   | 20.00 kB | 2018-11-04T20:32:09.768Z | root    | true      | false | false  | true    | true  | true  |
    | /                                    | true   |  4.00 kB | 2018-11-04T20:09:22.061Z | root    | true      | false | false  | true    | true  | true  |
    +--------------------------------------+--------+----------+--------------------------+---------+-----------+-------+--------+---------+-------+-------+
    

    如您所见,代码在调用之前检查目录是否存在 Files.createDirectories() Files.createDirectories() ,它继续失败。

    编辑:此代码由多个线程调用。这意味着多个线程可以调用 ,但如果目录最终存在,则代码不会重新引发异常。换句话说,其他线程必须在正确的时间创建和删除目录,因为 directory.exists() false 前后 Files.createDirectories() . 此外,这个完美的时机必须持续下去,因为一旦程序遇到这个问题,它就会针对特定的目录不断发生。

    2 回复  |  直到 7 年前
        1
  •  0
  •   Kartik    7 年前

    这段代码很可能被多个线程使用,因为只有这样才能解释为什么代码会进入 if 如果条件是 false

    synchronized (this) {
        if (!directory.exists())
            Files.createDirectories(path, attr);
    }
    
        2
  •  0
  •   Nathan    7 年前

    我不能经常重复这个问题。我决定替换 Files.createDirectories() 具有 Files.createDirectory() (即根据需要在路径中创建每个目录)。也许这会管用。也许这会揭示根本问题。

    推荐文章