¿Cómo crear un directorio/carpeta temporal en Java?

Resuelto Peter Becker asked hace 15 años • 18 respuestas

¿Existe una forma estándar y confiable de crear un directorio temporal dentro de una aplicación Java? Hay una entrada en la base de datos de problemas de Java , que tiene un poco de código en los comentarios, pero me pregunto si se puede encontrar una solución estándar en una de las bibliotecas habituales (Apache Commons, etc.).

Peter Becker avatar Mar 06 '09 08:03 Peter Becker
Aceptado

Si está utilizando JDK 7, utilice la nueva clase Files.createTempDirectory para crear el directorio temporal.

Path tempDirWithPrefix = Files.createTempDirectory(prefix);

Antes de JDK 7 esto debería funcionar:

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);
}

Podrías hacer mejores excepciones (subclase IOException) si lo deseas.

TofuBeer avatar Mar 06 '2009 01:03 TofuBeer

La biblioteca de Google Guava tiene un montón de utilidades útiles. Una cosa a tener en cuenta aquí es la clase Archivos . Tiene un montón de métodos útiles que incluyen:

File myTempDir = Files.createTempDir();

Esto hace exactamente lo que pediste en una línea. Si lee la documentación aquí, verá que la adaptación propuesta File.createTempFile("install", "dir")normalmente introduce vulnerabilidades de seguridad.

Spina avatar Jun 19 '2011 17:06 Spina

Si necesita un directorio temporal para realizar pruebas y está utilizando jUnit, @Ruleesto TemporaryFolderresuelve su problema:

@Rule
public TemporaryFolder folder = new TemporaryFolder();

De la documentación :

La regla de carpeta temporal permite la creación de archivos y carpetas que se garantiza que se eliminarán cuando finalice el método de prueba (ya sea que pase o falle).


Actualizar:

Si está utilizando JUnit Jupiter (versión 5.1.1 o superior), tiene la opción de utilizar JUnit Pioneer, que es el paquete de extensión JUnit 5.

Copiado de la documentación del proyecto :

Por ejemplo, la siguiente prueba registra la extensión para un único método de prueba, crea y escribe un archivo en el directorio temporal y verifica su contenido.

@Test
@ExtendWith(TempDirectory.class)
void test(@TempDir Path tempDir) {
    Path file = tempDir.resolve("test.txt");
    writeFile(file);
    assertExpectedFileContent(file);
}

Más información en el JavaDoc y el JavaDoc de TempDirectory

Gradle:

dependencies {
    testImplementation 'org.junit-pioneer:junit-pioneer:0.1.2'
}

experto:

<dependency>
   <groupId>org.junit-pioneer</groupId>
   <artifactId>junit-pioneer</artifactId>
   <version>0.1.2</version>
   <scope>test</scope>
</dependency>

Actualización 2:

La anotación @TempDir se agregó a la versión JUnit Jupiter 5.4.0 como característica experimental. Ejemplo copiado de la Guía del usuario de JUnit 5 :

@Test
void writeItemsToFile(@TempDir Path tempDir) throws IOException {
    Path file = tempDir.resolve("test.txt");

    new ListWriter(file).write("a", "b", "c");

    assertEquals(singletonList("a,b,c"), Files.readAllLines(file));
}
matsev avatar May 31 '2011 09:05 matsev

El código escrito ingenuamente para resolver este problema sufre condiciones de carrera, incluidas varias de las respuestas aquí. Históricamente, podría pensar detenidamente sobre las condiciones de carrera y escribirlas usted mismo, o podría usar una biblioteca de terceros como Guava de Google (como sugirió la respuesta de Spina). O podría escribir código con errores.

Pero a partir del JDK 7, ¡hay buenas noticias! La propia biblioteca estándar de Java ahora proporciona una solución que funciona correctamente (no es atractiva) para este problema. Quieres java.nio.file.Files#createTempDirectory() . De la documentación :

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

Crea un nuevo directorio en el directorio especificado, utilizando el prefijo dado para generar su nombre. La ruta resultante está asociada con el mismo sistema de archivos que el directorio dado.

Los detalles sobre cómo se construye el nombre del directorio dependen de la implementación y, por lo tanto, no se especifican. Siempre que sea posible, el prefijo se utiliza para construir nombres de candidatos.

Esto resuelve efectivamente el vergonzosamente antiguo informe de error en el rastreador de errores de Sun que solicitaba dicha función.

Greg Price avatar Oct 18 '2011 07:10 Greg Price

Este es el código fuente de Files.createTempDir() de la biblioteca Guava. No es tan complejo como podría pensar:

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) + ')');
}

Por defecto:

private static final int TEMP_DIR_ATTEMPTS = 10000;

Mira aquí

Andres Kievsky avatar Jan 25 '2012 06:01 Andres Kievsky