Determine a data de criação do arquivo em Java

102

Há outra questão semelhante a minha no StackOverflow ( como obter a data de criação de um arquivo em Java ), mas a resposta não está realmente lá, pois o OP tinha uma necessidade diferente que poderia ser resolvida por meio de outros mecanismos. Estou tentando criar uma lista dos arquivos em um diretório que pode ser classificado por idade, daí a necessidade da data de criação do arquivo.

Não encontrei uma boa maneira de fazer isso depois de pesquisar muito na web. Existe um mecanismo para obter as datas de criação do arquivo?

BTW, atualmente em um sistema Windows, pode precisar disso para funcionar em um sistema Linux também. Além disso, não posso garantir que uma convenção de nomenclatura de arquivo seja seguida onde a data / hora de criação está embutida no nome.

Todd
fonte
2
Ok, depois de mais discussões e investigações nos sistemas de arquivos, decidimos que usar a última modificação é suficiente, uma vez que provavelmente teria que ser verificado junto com a data de criação. Ambos precisariam ser verificados para determinar se um arquivo antigo foi modificado recentemente e, portanto, ainda está ativo. Portanto, apenas verifique o arquivo modificado mais distante no passado. Obrigado por todas as contribuições. BTW, eu adoraria usar o nio, mas o tipo Linux aqui não suporta a criação de arquivos de qualquer maneira.
Todd

Respostas:

163

Java nio tem opções para acessar o creationTime e outros metadados, desde que o sistema de arquivos os forneça. Confira neste link para fora

Por exemplo (fornecido com base no comentário 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 do anel
fonte
16
Seria melhor, mas é o Java 7. Ainda estamos usando o 6, mas investigarei nossas opções de atualização.
Todd
1
Fantástico. Exatamente eu precisava.
RestInPeace
7
use readAttributes(file.toPath(), BasicFileAttributes.class)outra coisa que você obtém: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 Não se preocupe, cara! Experimente este logicbig.com/how-to/java/file-creation-date.html .
Sócrates de
1
A data de criação do arquivo não está disponível no JDK 8 (pelo menos) desde que o statxsyscall foi adicionado na versão mais recente do kernel Linux.
St.Antario
15

Resolvi esse problema usando o JDK 7 com 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
fonte
13

Seguindo essa questão - uma vez que se relaciona especificamente ao tempo de criação e discute como obtê-lo por meio das novas classes nio - parece que agora na implementação do JDK7 você está sem sorte. Adendo: o mesmo comportamento é no OpenJDK7.

Em sistemas de arquivos Unix, você não pode recuperar o carimbo de data e hora da criação, simplesmente obtém uma cópia da hora da última modificação. Tão triste, mas infelizmente é verdade. Não sei por que isso acontece, mas o código faz isso especificamente, conforme demonstrará a seguir.

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
fonte
1
Você sabe como fazer isso no Android? BasicFileAttributes não está disponível como API integrada lá ...
desenvolvedor de Android
Isso é verdade, mesmo uma chamada para statnão funciona. A menos que você execute um kernel superior a 4.11 com glibc superior a 2.28 e coreutils superior a 8.31, então statirá relatar o nascimento do arquivo. Veja a resposta relacionada unix.stackexchange.com/questions/50177/birth-is-empty-on-ext4/… Atualmente o JDK não usa statx syscal.
Brice de
12

Este é um exemplo básico de como obter a data de criação de um arquivo Java, usando a BasicFileAttributesclasse:

   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
fonte
As pessoas que desejam usar essa classe devem observar que ela começou a ser enviada em Java 1.7.
jwj
9

A API de java.io.Filesuporta apenas a última modificação hora . E a Internet também não fala muito sobre esse assunto.

A menos que eu tenha perdido algo significativo, a biblioteca Java como está (até mas ainda não incluindo o Java 7) não inclui esse recurso. Portanto, se você estivesse desesperado por isso, uma solução seria escrever algum código C (++) para chamar as rotinas do sistema e chamá-lo usando JNI. A maior parte deste trabalho parece já ter sido feita para você em uma biblioteca chamada JNA , no entanto.

Você ainda pode precisar fazer uma pequena codificação específica do sistema operacional em Java para isso, pois provavelmente não encontrará as mesmas chamadas de sistema disponíveis no Windows e Unix / Linux / BSD / OS X.

Carl Smotricz
fonte
2
Sim, Java 7 seria ótimo, pois o nio parece ter isso em atributos básicos. Nunca pensei que reclamaria por ter nascido muito cedo! ;)
Todd,
6
A razão pela qual a Fileclasse não tem esse recurso é que a maioria dos sistemas de arquivos nem mesmo rastreia essas informações. E aqueles que concordam nem sempre concordam quando deve ser atualizado.
Syntactic
@Syntactic: Na verdade, a maioria dos sistemas de arquivos rastreia essas informações . As exceções incluem ext <= 3 e Reiser. FAT, NTFS, HFS, ZFS e ext4 são compatíveis. Mas tem sido lento para se propagar por todas as camadas do Linux e as bibliotecas e comandos para torná-lo universalmente usado.
hippietrail
@Carl No linux, estou obtendo a data de modificação e criação da mesma forma ao usar o Java NIO. É o comportamento normal?
Jayesh Dhandha
@JayeshDhandha, se nada modificar o arquivo depois de criado, esperaria que os tempos de criação e modificação fossem iguais. Você pode tentar mudar isso usando touchpara mudar o tempo do mod e depois verificar novamente.
Carl Smotricz
9

Em um sistema Windows, você pode usar FileTimes grátis biblioteca .

Isso será mais fácil no futuro com Java NIO.2 (JDK 7) e o pacote java.nio.file.attribute .

Mas lembre-se de que a maioria dos sistemas de arquivos Linux não oferece suporte a carimbos de data / hora de criação de arquivo .

Jacek S
fonte
Alguma outra maneira de contornar as máquinas Linux que não suportam o tempo criado?
Maverick de
Basta usar um sistema de arquivos que suporte carimbos de data / hora de criação de arquivo. O artigo da Wikipedia com link sugere ext4, que é bastante comum agora.
davtom
1

em java1.7 + Você pode usar este código para obter o tempo de criação do arquivo!

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
fonte
você poderia explicar por que precisamos dessa agitação Instant.ofEpochMilli(date). Obrigado
Kirill Karmazin