java - linux创建文件夹 - scala创建文件夹




如何在Java中创建临时目录/文件夹? (12)

在Java应用程序中创建临时目录是否有标准可靠的方法? 在Java的问题数据库中一个条目 ,它在注释中有一些代码,但我想知道是否有一个标准解决方案可以在常见的库(Apache Commons等)中找到?


为解决这个问题,天真的代码会遇到竞争条件,包括这里的几个答案。 从历史上看,你可以仔细考虑竞争条件并自己写,或者你可以使用像谷歌的番石榴这样的第三方库(正如Spina的答案所建议的那样)。或者你可以编写错误的代码。

但从JDK 7开始,就有好消息! Java标准库本身现在提供了适用于此问题的正确工作(非活动)解决方案。 你想要java.nio.file.Files#createTempDirectory() 。 从java.nio.file.Files#createTempDirectory()

public static Path createTempDirectory(Path dir,
                       String prefix,
                       FileAttribute<?>... attrs)
                                throws IOException

在指定的目录中创建一个新目录,使用给定的前缀来生成其名称。 生成的Path与给定目录的FileSystem相关联。

有关如何构建目录名称的细节与实现相关,因此未指定。 在可能的情况下,前缀用于构建候选名称。

这有效地解决了Sun Bug跟踪器中那个仅仅需要这样一个功能的令人尴尬的古老bug报告


从Java 1.7开始, createTempDirectory(prefix, attrs)createTempDirectory(dir, prefix, attrs)包含在java.nio.file.Files

例如: File tempDir = Files.createTempDirectory("foobar").toFile();


即使您稍后明确删除,也不要使用deleteOnExit()

谷歌的'deleteonexit是邪恶'的更多信息,但问题的要点是:

  1. deleteOnExit()只会删除正常的JVM关闭,而不会崩溃或终止JVM进程。

  2. deleteOnExit()仅在JVM关闭时删除 - 对于长时间运行的服务器进程deleteOnExit()因为:

  3. 全部最邪恶的 - deleteOnExit()消耗每个临时文件条目的内存。 如果您的进程运行数月,或在短时间内创建大量临时文件,则会消耗内存并在JVM关闭之前从不释放它。


只是为了完成,这是谷歌guava库的代码。 这不是我的代码,但我认为在此线程中显示它是有价值的。

  /** Maximum loop count when creating temp directories. */
  private static final int TEMP_DIR_ATTEMPTS = 10000;

  /**
   * Atomically creates a new directory somewhere beneath the system's temporary directory (as
   * defined by the {@code java.io.tmpdir} system property), and returns its name.
   *
   * <p>Use this method instead of {@link File#createTempFile(String, String)} when you wish to
   * create a directory, not a regular file. A common pitfall is to call {@code createTempFile},
   * delete the file and create a directory in its place, but this leads a race condition which can
   * be exploited to create security vulnerabilities, especially when executable files are to be
   * written into the directory.
   *
   * <p>This method assumes that the temporary volume is writable, has free inodes and free blocks,
   * and that it will not be called thousands of times per second.
   *
   * @return the newly-created directory
   * @throws IllegalStateException if the directory could not be created
   */
  public static File createTempDir() {
    File baseDir = new File(System.getProperty("java.io.tmpdir"));
    String baseName = System.currentTimeMillis() + "-";

    for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
      File tempDir = new File(baseDir, baseName + counter);
      if (tempDir.mkdir()) {
        return tempDir;
      }
    }
    throw new IllegalStateException(
        "Failed to create directory within "
            + TEMP_DIR_ATTEMPTS
            + " attempts (tried "
            + baseName
            + "0 to "
            + baseName
            + (TEMP_DIR_ATTEMPTS - 1)
            + ')');
  }

如果您使用的是JDK 7,请使用新的Files.createTempDirectory类创建临时目录。

在JDK 7之前,应该这样做:

public static File createTempDirectory()
    throws IOException
{
    final File temp;

    temp = File.createTempFile("temp", Long.toString(System.nanoTime()));

    if(!(temp.delete()))
    {
        throw new IOException("Could not delete temp file: " + temp.getAbsolutePath());
    }

    if(!(temp.mkdir()))
    {
        throw new IOException("Could not create temp directory: " + temp.getAbsolutePath());
    }

    return (temp);
}

如果你愿意,你可以做出更好的异常(子类IOException)。



我遇到了同样的问题,所以这对于那些有兴趣的人来说只是另一个答案,并且与上述类似:

public static final String tempDir = System.getProperty("java.io.tmpdir")+"tmp"+System.nanoTime();
static {
    File f = new File(tempDir);
    if(!f.exists())
        f.mkdir();
}

对于我的应用程序,我决定添加一个选项来清除退出时的温度 ,所以我添加了一个关闭钩子:

Runtime.getRuntime().addShutdownHook(new Thread() {
        @Override
        public void run() {
            //stackless deletion
            String root = MainWindow.tempDir;
            Stack<String> dirStack = new Stack<String>();
            dirStack.push(root);
            while(!dirStack.empty()) {
                String dir = dirStack.pop();
                File f = new File(dir);
                if(f.listFiles().length==0)
                    f.delete();
                else {
                    dirStack.push(dir);
                    for(File ff: f.listFiles()) {
                        if(ff.isFile())
                            ff.delete();
                        else if(ff.isDirectory())
                            dirStack.push(ff.getPath());
                    }
                }
            }
        }
    });

该方法在删除temp之前删除所有的子文件和文件,而不使用callstack(这是完全可选的,你可以在这一点上使用递归),但是我想保持安全。


正如本RFE及其评论中所述,您可以先调用tempDir.delete() 。 或者你可以使用System.getProperty("java.io.tmpdir")并在那里创建一个目录。 无论哪种方式,您都应该记得调用tempDir.deleteOnExit() ,否则在完成后文件不会被删除。


谷歌Guava图书馆有很多有用的工具。 其中一个注意事项是Files类 。 它有一堆有用的方法,包括:

File myTempDir = Files.createTempDir();

这正是你在一行中所要求的。 如果您在here阅读文档here您会看到File.createTempFile("install", "dir")的建议修改通常会引入安全漏洞。


这是Guava库的Files.createTempDir()的源代码。 它不像您想象的那么复杂:

public static File createTempDir() {
  File baseDir = new File(System.getProperty("java.io.tmpdir"));
  String baseName = System.currentTimeMillis() + "-";

  for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
    File tempDir = new File(baseDir, baseName + counter);
    if (tempDir.mkdir()) {
      return tempDir;
    }
  }
  throw new IllegalStateException("Failed to create directory within "
      + TEMP_DIR_ATTEMPTS + " attempts (tried "
      + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')');
}

默认:

private static final int TEMP_DIR_ATTEMPTS = 10000;

看这里


这段代码应该工作得很好:

public static File createTempDir() {
    final String baseTempPath = System.getProperty("java.io.tmpdir");

    Random rand = new Random();
    int randomInt = 1 + rand.nextInt();

    File tempDir = new File(baseTempPath + File.separator + "tempDir" + randomInt);
    if (tempDir.exists() == false) {
        tempDir.mkdir();
    }

    tempDir.deleteOnExit();

    return tempDir;
}

那么,“createTempFile”实际上会创建该文件。 那么为什么不先删除它,然后在其上执行mkdir?







temporary-directory