Określ datę utworzenia pliku w Javie

102

Jest jeszcze jedno podobne pytanie do mojego w StackOverflow ( Jak uzyskać datę utworzenia pliku w Javie ), ale odpowiedzi nie ma, ponieważ OP miał inną potrzebę, którą można rozwiązać za pomocą innych mechanizmów. Próbuję stworzyć listę plików w katalogu, które można sortować według wieku, stąd potrzeba daty utworzenia pliku.

Nie znalazłem żadnego dobrego sposobu, aby to zrobić po wielu przeglądach sieci. Czy istnieje mechanizm pobierania dat utworzenia pliku?

BTW, obecnie w systemie Windows, może potrzebować tego do pracy również w systemie Linux. Nie mogę również zagwarantować, że będzie przestrzegana konwencja nazewnictwa plików, gdy data / godzina utworzenia jest osadzona w nazwie.

Todd
źródło
2
OK, po dalszych dyskusjach i badaniach systemów plików zdecydowaliśmy, że użycie ostatniej modyfikacji jest wystarczające, ponieważ prawdopodobnie musiałoby zostać sprawdzone wraz z datą utworzenia. Oba musiałyby zostać sprawdzone, aby określić, czy stary plik został niedawno zmodyfikowany, a zatem nadal jest aktywny. Po prostu poszukaj pliku zmodyfikowanego najdalej w przeszłości. Dzięki za cały wkład. Przy okazji, chciałbym użyć nio, ale wersja Linuksa i tak nie obsługuje tworzenia plików.
Todd

Odpowiedzi:

163

Java nio ma opcje dostępu do czasu utworzenia i innych metadanych, o ile zapewnia je system plików. Sprawdzić ten link na zewnątrz

Na przykład (dostarczone na podstawie komentarza @ 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());
posiadacz pierścienia
źródło
16
Byłoby najlepiej, ale to Java 7. Nadal używamy 6, ale zbadam nasze opcje aktualizacji.
Todd
1
Fantastyczny. Dokładnie potrzebowałem.
RestInPeace
7
użyj readAttributes(file.toPath(), BasicFileAttributes.class)innego dostaniesz: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 Nie martw się, stary! Wypróbuj to logicbig.com/how-to/java/file-creation-date.html .
Sokrates
1
Data utworzenia pliku nie jest dostępna w JDK 8 (przynajmniej), ponieważ statxsyscall został dodany w nowszej wersji jądra Linuksa.
St.Antario
15

Rozwiązałem ten problem używając JDK 7 z tym kodem:

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
źródło
13

W ramach kontynuacji tego pytania - ponieważ odnosi się ono konkretnie do czasu tworzenia i omawia uzyskanie go za pośrednictwem nowych klas nio - wydaje się, że teraz w implementacji JDK7 nie masz szczęścia. Dodatek: to samo zachowanie jest w OpenJDK7.

Na systemach plików Unix nie możesz pobrać znacznika czasu utworzenia, po prostu dostajesz kopię czasu ostatniej modyfikacji. Tak smutne, ale niestety prawdziwe. Nie jestem pewien, dlaczego tak jest, ale kod specjalnie to robi, co pokaże poniżej.

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
źródło
1
Czy wiesz, jak to zrobić na Androida? BasicFileAttributes nie jest dostępna w postaci wbudowanego interfejsu API ...
programista android
To rzeczywiście prawda, nawet wezwanie do statnie działa. O ile nie uruchomisz jądra w wersji wyższej niż 4.11 z glibc wyższym niż 2.28 i coreutils w wersji wyższej niż 8.31, wtedy statzgłosi narodziny pliku. Zobacz powiązaną odpowiedź unix.stackexchange.com/questions/50177/birth-is-empty-on-ext4/… Obecnie JDK nie używa statx syscal.
Brice
12

Oto podstawowy przykład, jak uzyskać datę utworzenia pliku Javaza pomocą 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
źródło
Osoby, które chcą korzystać z tej klasy, powinny zauważyć, że zaczęła ona być dostępna w Javie 1.7.
jwj
9

API java.io.Fileobsługuje tylko pobieranie czasu ostatniej modyfikacji . Internet jest też bardzo cichy na ten temat.

O ile nie przeoczyłem czegoś ważnego, biblioteka Java taka, jaka jest (do Javy 7, ale jeszcze jej nie obejmuje) nie obejmuje tej możliwości. Więc gdybyś był zdesperowany, jednym z rozwiązań byłoby napisanie kodu w C (++) do wywoływania procedur systemowych i wywoływanie go przy użyciu JNI. Wydaje się jednak, że większość tej pracy została już wykonana dla Ciebie w bibliotece o nazwie JNA .

Być może nadal będziesz musiał wykonać trochę kodowania specyficznego dla systemu operacyjnego w Javie, ponieważ prawdopodobnie nie znajdziesz tych samych wywołań systemowych dostępnych w Windows i Unix / Linux / BSD / OS X.

Carl Smotricz
źródło
2
Tak, Java 7 byłaby świetna, ponieważ nio wydaje się mieć to w podstawowych atrybutach. Nigdy nie sądziłem, że będę narzekać, że urodziłem się za wcześnie! ;)
Todd
6
Powodem, dla którego Fileklasa nie ma tej możliwości, jest to, że większość systemów plików nawet nie śledzi tych informacji. A ci, którzy się zgadzają, nie zawsze są zgodni co do tego, kiedy należy go zaktualizować.
Syntactic
@Syntactic: Właściwie większość systemów plików śledzi te informacje . Wyjątki obejmują ext <= 3 i Reiser. Obsługują go FAT, NTFS, HFS, ZFS i ext4. Jednak rozprzestrzenianie się we wszystkich warstwach Linuksa oraz bibliotekach i poleceniach było powolne, aby uczynić go powszechnie używanym.
hippietrail
@Carl W Linuksie otrzymuję taką samą datę modyfikacji i utworzenia przy używaniu Java NIO. Czy to normalne zachowanie?
Jayesh Dhandha
@JayeshDhandha, jeśli nic nie modyfikuje pliku po jego utworzeniu, spodziewałbym się , że czasy tworzenia i modyfikacji będą równe. Możesz spróbować to zmienić, używając touchdo zmiany czasu modyfikacji, a następnie sprawdzając ponownie.
Carl Smotricz
9

W systemie Windows możesz skorzystać z bezpłatnej biblioteki FileTimes .

W przyszłości będzie to łatwiejsze dzięki Java NIO.2 (JDK 7) i pakietowi java.nio.file.attribute .

Pamiętaj jednak, że większość systemów plików Linuksa nie obsługuje znaczników czasu tworzenia plików .

Jacek S.
źródło
Czy jest jakieś inne rozwiązanie dla maszyn linuxowych, które nie obsługują czasu stworzonego?
Maverick
Po prostu użyj systemu plików, który obsługuje znaczniki czasu tworzenia plików. Link do artykułu z Wikipedii sugeruje ext4, który jest obecnie dość powszechny.
davtom
1

w java1.7 + Możesz użyć tego kodu, aby uzyskać czas utworzenia pliku!

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
źródło
czy mógłbyś wyjaśnić, dlaczego potrzebujemy tego pośpiechu Instant.ofEpochMilli(date). Dzięki
Kirill Karmazin