Determinar la fecha de creación del archivo en Java

102

Hay otra pregunta similar a la mía en StackOverflow ( Cómo obtener la fecha de creación de un archivo en Java ), pero la respuesta no está realmente ahí, ya que el OP tenía una necesidad diferente que podría resolverse a través de otros mecanismos. Estoy tratando de crear una lista de los archivos en un directorio que se puede ordenar por edad, de ahí la necesidad de la fecha de creación del archivo.

No he encontrado ninguna buena manera de hacer esto después de mucho rastrear la web. ¿Existe un mecanismo para obtener las fechas de creación de archivos?

Por cierto, actualmente en un sistema Windows, puede necesitar esto para que funcione también en un sistema Linux. Además, no puedo garantizar que se siga una convención de nomenclatura de archivos donde la fecha / hora de creación esté incrustada en el nombre.

Todd
fuente
2
Bien, después de más discusiones e investigaciones sobre los sistemas de archivos, hemos decidido que usar la última modificación es suficiente, ya que es probable que se haya verificado junto con la fecha de creación. Ambos deberían verificarse para determinar si un archivo antiguo se modificó recientemente y, por lo tanto, sigue activo. Por lo tanto, solo verifique el archivo modificado más lejano en el pasado. Gracias por todos los aportes. Por cierto, me encantaría usar nio, pero el sabor de Linux aquí no admite la creación de archivos de todos modos.
Todd

Respuestas:

163

Java nio tiene opciones para acceder a creationTime y otros metadatos siempre que el sistema de archivos lo proporcione. Compruebe este enlace a cabo

Por ejemplo (proporcionado según el comentario de @ ydaetskcoR):

Path file = ...;
BasicFileAttributes attr = Files.readAttributes(file, BasicFileAttributes.class);

System.out.println("creationTime: " + attr.creationTime());
System.out.println("lastAccessTime: " + attr.lastAccessTime());
System.out.println("lastModifiedTime: " + attr.lastModifiedTime());
portador del anillo
fuente
16
Esto sería lo mejor, pero es Java 7. Todavía estamos usando 6, pero investigaré nuestras opciones de actualización.
Todd
1
Fantástico. Exactamente lo necesitaba.
RestInPeace
7
use lo readAttributes(file.toPath(), BasicFileAttributes.class)demás que obtenga:no suitable method found for readAttributes(File,Class<BasicFileAttributes>) method Files.<A>readAttributes(Path,Class<A>,LinkOption...) is not applicable (cannot infer type-variable(s) A (argument mismatch; File cannot be converted to Path))
Hooli
1
@Hooli ¡No te preocupes, amigo! Pruebe este logicbig.com/how-to/java/file-creation-date.html .
Sócrates
1
La fecha de creación del archivo no está disponible en JDK 8 (al menos) ya que statxsyscall se agregó en la versión más reciente del kernel de Linux.
St.Antario
15

Resolví este problema usando JDK 7 con este código:

package FileCreationDate;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Date;
import java.util.concurrent.TimeUnit;

public class Main
{
    public static void main(String[] args) {

        File file = new File("c:\\1.txt");
        Path filePath = file.toPath();

        BasicFileAttributes attributes = null;
        try
        {
            attributes =
                    Files.readAttributes(filePath, BasicFileAttributes.class);
        }
        catch (IOException exception)
        {
            System.out.println("Exception handled when trying to get file " +
                    "attributes: " + exception.getMessage());
        }
        long milliseconds = attributes.creationTime().to(TimeUnit.MILLISECONDS);
        if((milliseconds > Long.MIN_VALUE) && (milliseconds < Long.MAX_VALUE))
        {
            Date creationDate =
                    new Date(attributes.creationTime().to(TimeUnit.MILLISECONDS));

            System.out.println("File " + filePath.toString() + " created " +
                    creationDate.getDate() + "/" +
                    (creationDate.getMonth() + 1) + "/" +
                    (creationDate.getYear() + 1900));
        }
    }
}
Oleksandr Tarasenko
fuente
13

Como seguimiento a esta pregunta, ya que se relaciona específicamente con el tiempo de creación y analiza cómo obtenerlo a través de las nuevas clases nio, parece que en este momento en la implementación de JDK7 no tiene suerte. Anexo: el mismo comportamiento está en OpenJDK7.

En los sistemas de archivos Unix no puede recuperar la marca de tiempo de creación, simplemente obtiene una copia de la última hora de modificación. Muy triste, pero lamentablemente cierto. No estoy seguro de por qué es eso, pero el código lo hace específicamente como lo demostrará a continuación.

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.*;

public class TestFA {
  static void getAttributes(String pathStr) throws IOException {
    Path p = Paths.get(pathStr);
    BasicFileAttributes view
       = Files.getFileAttributeView(p, BasicFileAttributeView.class)
              .readAttributes();
    System.out.println(view.creationTime()+" is the same as "+view.lastModifiedTime());
  }
  public static void main(String[] args) throws IOException {
    for (String s : args) {
        getAttributes(s);
    }
  }
}
David Nugent
fuente
1
¿Sabes cómo hacerlo para Android? BasicFileAttributes no está disponible como API integrada allí ...
desarrollador de Android
De hecho, esto es cierto, incluso una llamada a statno funciona. A menos que ejecute un kernel superior a 4.11 con glibc superior a 2.28 y coreutils superior a 8.31, entonces statinformará el nacimiento del archivo. Consulte la respuesta relacionada unix.stackexchange.com/questions/50177/birth-is-empty-on-ext4/… Actualmente, el JDK no usa statx syscal.
Brice
12

Este es un ejemplo básico de cómo obtener la fecha de creación de un archivo Java, usando BasicFileAttributesclass:

   Path path = Paths.get("C:\\Users\\jorgesys\\workspaceJava\\myfile.txt");
    BasicFileAttributes attr;
    try {
    attr = Files.readAttributes(path, BasicFileAttributes.class);
    System.out.println("Creation date: " + attr.creationTime());
    //System.out.println("Last access date: " + attr.lastAccessTime());
    //System.out.println("Last modified date: " + attr.lastModifiedTime());
    } catch (IOException e) {
    System.out.println("oops error! " + e.getMessage());
}
Jorgesys
fuente
Las personas que deseen usar esta clase deben tener en cuenta que comenzó a distribuirse en Java 1.7.
jwj
9

La API de java.io.Filesolo admite obtener la última hora modificada . E Internet también es muy silencioso sobre este tema.

A menos que me haya perdido algo importante, la biblioteca de Java tal como está (hasta Java 7, pero sin incluirla) no incluye esta capacidad. Entonces, si estuviera desesperado por esto, una solución sería escribir un código C (++) para llamar a las rutinas del sistema y llamarlo usando JNI. Sin embargo, parece que la mayor parte de este trabajo ya está hecho en una biblioteca llamada JNA .

Sin embargo, es posible que deba realizar una pequeña codificación específica del sistema operativo en Java para esto, ya que probablemente no encontrará las mismas llamadas al sistema disponibles en Windows y Unix / Linux / BSD / OS X.

Carl Smotricz
fuente
2
Sí, Java 7 sería genial ya que nio parece tener esto en atributos básicos. ¡Nunca pensé que me quejaría de haber nacido demasiado pronto! ;)
Todd
6
La razón por la que la Fileclase no tiene esta capacidad es que la mayoría de los sistemas de archivos ni siquiera rastrean esta información. Y aquellos que lo hacen no siempre están de acuerdo en cuándo debería actualizarse.
Sintáctico
@Syntactic: En realidad, la mayoría de los sistemas de archivos rastrean esta información . Las excepciones incluyen ext <= 3 y Reiser. FAT, NTFS, HFS, ZFS y ext4 lo admiten. Pero ha sido lento en propagarse a través de todas las capas de Linux y las bibliotecas y comandos para que sea de uso universal.
hippietrail
@Carl En Linux, obtengo la misma fecha de modificación y creación mientras uso Java NIO. ¿Es el comportamiento normal?
Jayesh Dhandha
@JayeshDhandha, si nada modifica el archivo después de su creación, esperaría que los tiempos de creación y modificación sean iguales. Puede intentar cambiar eso usando touchpara cambiar el tiempo de modulación y luego verificando nuevamente.
Carl Smotricz
9

En un sistema Windows, puede usar la biblioteca FileTimes gratuita .

Esto será más fácil en el futuro con Java NIO.2 (JDK 7) y el paquete java.nio.file.attribute .

Pero recuerde que la mayoría de los sistemas de archivos de Linux no admiten las marcas de tiempo de creación de archivos .

Jacek S
fuente
¿Alguna otra forma para las máquinas Linux que no admiten el tiempo creado?
Maverick
Simplemente use un sistema de archivos que admita marcas de tiempo de creación de archivos. El artículo de Wikipedia vinculado sugiere ext4, que es bastante común ahora.
davtom
1

en java1.7 + ¡Puedes usar este código para obtener el tiempo de creación del archivo!

private static LocalDateTime getCreateTime(File file) throws IOException {
        Path path = Paths.get(file.getPath());
        BasicFileAttributeView basicfile = Files.getFileAttributeView(path, BasicFileAttributeView.class, LinkOption.NOFOLLOW_LINKS);
        BasicFileAttributes attr = basicfile.readAttributes();
        long date = attr.creationTime().toMillis();
        Instant instant = Instant.ofEpochMilli(date);
        return LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
    }
zhangxinqiang
fuente
¿Podría explicarnos por qué necesitamos este ajetreo Instant.ofEpochMilli(date)? Gracias
Kirill Karmazin