2014-07-17 19 views
8

Po przeczytaniu mtime pliku z Java przy użyciu Files.getLastModifiedTime, zwracana wartość jest obcinana do całych sekund. Wiem, że działa to na innych systemach, aby uzyskać mtime z rozdzielczością milisekundy, więc co może być innego w moim?Pobierz plik mtime z rozdzielczością milisekundową z Java

Powyżej znajduje się pełna próba samodzielna który kompiluje i uruchamia:

import java.nio.file.attribute.FileTime; 
import java.nio.file.Files; 
import java.nio.file.Paths; 
public class Test { 
    public static void main(String[] args) throws java.io.IOException { 
    FileTime timestamp = Files.getLastModifiedTime(Paths.get("/tmp/test")); 
    System.out.println(timestamp.toMillis()); 
    } 
} 

Wyjście jest (z mojego konkretnego pliku testowego) 1405602038000, natomiast ls Wystawy:

$ ls --full-time /tmp/test                                                  
-rw-rw-r-- 1 daniel daniel 0 2014-07-17 16:00:38.413008992 +0300 /tmp/test 

spodziewałbym Java wyjście to 1405602038413.

Używam systemu Linux z ext4. Próbowałem zarówno openjdk 1.7, jak i Oracle jdk 1.8.

Odpowiedz

7

zdolność do uzyskania znaczników czasu plików na systemach * nix z większą dokładnością dodano w Java 8 przez this commit jednak na rodzimej strony, wymaga POSIX 2008 zgodność:

#if (_POSIX_C_SOURCE >= 200809L) || defined(__solaris__) 
    (*env)->SetLongField(env, attrs, attrs_st_atime_nsec, (jlong)buf->st_atim.tv_nsec); 
    (*env)->SetLongField(env, attrs, attrs_st_mtime_nsec, (jlong)buf->st_mtim.tv_nsec); 
    (*env)->SetLongField(env, attrs, attrs_st_ctime_nsec, (jlong)buf->st_ctim.tv_nsec); 
#endif 

I, najwyraźniej, Kompilacja Java, której używasz, nie ustawia jej, więc nanosekunda część znacznika czasu jest niedostępna i pozostaje zerowa.

-4

Można użyć prostego format daty do wyświetlania czasu jest milisekund:

java.nio.file.attribute.FileTime time = java.nio.file.Files.getLastModifiedTime(java.nio.file.Paths.get("/tmp/test")) 
java.text.SimpleDateFormat dateformat = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); 
System.out.println(dateformat.format(time.toMillis())); 
+1

nie zrozumiałeś. Wartość zwrócona przez 'time.toMillis' jest już obcięta do rozdzielczości drugiej sekundy (tzn. Zawsze kończy się na trzech zerach). To jest złe. – danarmak

+0

To wydaje się dziwne, ponieważ gdy próbuję tego na moim komputerze, mam rozdzielczość milisekundową. – lerobyte

+0

Jestem świadomy, że to działa dla innych (redagowałem to pytanie, aby to wyjaśnić), ale to nie działa tutaj i próbuję zrozumieć dlaczego. – danarmak

3

Spojrzałem na kodzie źródłowym:

W przypadku Java 7, metoda daje ostatnio modyfikowany znacznik czasu z 1 drugi precyzja:

W przypadku Javy 8, to wygląda powinno dać precyzję mikrosekund:

Ale w każdym przypadku, kod nie wydają się stanowić sposób, aby pobrać znacznik czasu z inną precyzją.

+0

[To '# if'] (http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.C# l437) wydaje się być spokrewniony. Jestem w stanie odtworzyć problem z Oracle Java 8 na Ubuntu. – izstas

+1

Kiedy patrzę z debuggerem na 'UnixFileAttributes.st_mtime', to już za całe sekundy. Coś jest nie tak z rodzimą stroną. Ponadto, nie mogę uzyskać millis nawet podczas używania w Javie 8 (the oracle build, not openjdk). Czy rzeczywiście możesz uzyskać millis po uruchomieniu java 8? – danarmak

+1

@izstas bingo! Jestem też na ubuntu. Teraz musimy tylko wiedzieć, dlaczego kompilacje Ubuntu (i kompilacja Oracle!) Nie powodują zgodności z POSIX2008. Czy kompilacje dla innych systemów operacyjnych lub dystrybucji ustawiają go? Jakie są osoby, dla których działa ten kod? Jeśli uczynisz to w odpowiedzi, zaakceptuję to i dzięki! – danarmak

0

Wydaje się być ustalona w java 9

  • Oracle jdk 9.0.4 - Files.getLastModifiedTime daje rozdzielczość milisekundy
  • Oracle JDK 1.8.162 - Files.getLastModifiedTime daje Druga rezolucja