Как создать временный каталог / папку в Java? - PullRequest
324 голосов
/ 06 марта 2009

Существует ли стандартный и надежный способ создания временного каталога в приложении Java? В базе данных проблем Java есть запись , в которой есть небольшой код в комментариях, но мне интересно, есть ли стандартное решение, которое можно найти в одной из обычных библиотек (Apache Commons и т. Д.)?

Ответы [ 17 ]

3 голосов
/ 21 июня 2016

Просто для завершения, это код из библиотеки Google 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)
            + ')');
  }
3 голосов
/ 17 декабря 2008

Как обсуждалось в этом RFE и его комментариях, вы могли бы сначала позвонить tempDir.delete(). Или вы можете использовать System.getProperty("java.io.tmpdir") и создать там каталог. В любом случае, вы должны не забыть позвонить tempDir.deleteOnExit(), иначе файл не будет удален после того, как вы закончите.

2 голосов
/ 24 июня 2014

Как видно из других ответов, стандартного подхода не возникло. Следовательно, вы уже упомянули Apache Commons, я предлагаю следующий подход с использованием FileUtils из Apache Commons IO :

/**
 * Creates a temporary subdirectory in the standard temporary directory.
 * This will be automatically deleted upon exit.
 * 
 * @param prefix
 *            the prefix used to create the directory, completed by a
 *            current timestamp. Use for instance your application's name
 * @return the directory
 */
public static File createTempDirectory(String prefix) {

    final File tmp = new File(FileUtils.getTempDirectory().getAbsolutePath()
            + "/" + prefix + System.currentTimeMillis());
    tmp.mkdir();
    Runtime.getRuntime().addShutdownHook(new Thread() {

        @Override
        public void run() {

            try {
                FileUtils.deleteDirectory(tmp);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    });
    return tmp;

}

Это предпочтительно, так как apache объединяет библиотеку, которая наиболее близка к запрашиваемому «стандарту» и работает как с JDK 7, так и с более старыми версиями. Это также возвращает «старый» экземпляр File (который основан на потоке), а не «новый» экземпляр Path (который основан на буфере и будет результатом метода getDeventDirectory ()) JDK7 -> Поэтому он возвращает то, что нужно большинству людей, когда они хотят создать временный каталог.

2 голосов
/ 29 января 2013

У меня такая же проблема, так что это просто еще один ответ для тех, кто заинтересован, и он похож на один из приведенных выше:

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

И для своего приложения я решил добавить опцию для очистки temp при выходе, поэтому добавил в ловушку отключения:

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 , без использования стека вызовов (что совершенно необязательно, и вы можете сделать это с рекурсией на этом этапе), но я хочу быть в безопасности сторона.

1 голос
/ 15 мая 2017

До Java 7 вы также могли:

File folder = File.createTempFile("testFileUtils", ""); // no suffix
folder.delete();
folder.mkdirs();
folder.deleteOnExit();
1 голос
/ 12 января 2011

Мне нравятся множественные попытки создания уникального имени, но даже это решение не исключает условия гонки. Другой процесс может включиться после теста для exists() и вызова метода if(newTempDir.mkdirs()). Я понятия не имею, как полностью сделать это безопасным, не прибегая к нативному коду, который, как я предполагаю, это то, что скрыто внутри File.createTempFile().

0 голосов
/ 06 марта 2009

Использование File#createTempFile и delete для создания уникального имени для каталога выглядит нормально. Вы должны добавить ShutdownHook, чтобы удалить каталог (рекурсивно) при завершении работы JVM.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...