2014-07-17 9 views
8

Quando ho letto il di un file da Java utilizzando Files.getLastModifiedTime, il valore restituito viene troncato a interi secondi. So che questo funziona su altri sistemi per ottenere mtimes con risoluzione al millisecondo, quindi cosa potrebbe essere diverso dal mio?Ottieni file mtime con una risoluzione al millisecondo da Java

Ecco un test stand-alone completo che riunisce e gestisce:

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

L'uscita è (con il mio particolare file di prova) 1405602038000, mentre ls spettacoli:

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

mi aspetterei Java uscita per essere 1405602038413.

Sono in esecuzione su Linux con ext4. Ho provato sia openjdk 1.7 che Oracle jdk 1.8.

risposta

7

la capacità di ottenere i timestamp di file sui sistemi * nix con maggiore precisione è stato aggiunto in Java 8 da this commit, tuttavia, sul lato nativo, richiede POSIX 2008 rispetto:

#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 

E, a quanto pare, il La build di Java che stai usando non la imposta, quindi la parte di nanosecondi del timestamp non è disponibile e rimane zero.

-4

È possibile utilizzare il semplice formato di data per visualizzare il tempo è millisecondi:

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

hai frainteso. Il valore restituito da 'time.toMillis' è già troncato a risoluzione del secondo intero (cioè termina sempre in tre zeri). Questo è ciò che è sbagliato. – danarmak

+0

Sembra strano, perché quando lo provo sul mio computer, ottengo una risoluzione al millisecondo. – lerobyte

+0

Sono consapevole che funziona per gli altri (ho modificato la domanda per chiarirlo), ma non funziona qui e sto cercando di capire perché. – danarmak

3

ho guardato il codice sorgente:

Nel caso Java 7, il metodo dà l'ultimo timestamp modificato con 1 secondo la precisione:

Nel caso Java 8, si sembra dovrebbe dare microsecondo precisione:

Ma in entrambi i casi, il codice non sembra fornire un modo per ottenere il timestamp con una precisione diversa.

+0

[Questo '# if'] (http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/solaris/native/sun/nio/fs/UnixNativeDispatcher.C# l437) sembra essere correlato. Sono in grado di riprodurre il problema con Oracle Java 8 su Ubuntu. – izstas

+1

Quando guardo con un debugger su 'UnixFileAttributes.st_mtime', è già in interi secondi. Qualcosa non va nella parte nativa. Inoltre, non riesco a ottenere millis anche quando si utilizza in Java 8 (la build di Oracle, non openjdk). Puoi davvero ottenere millis quando esegui java 8? – danarmak

+1

@izstas bingo! Anch'io sono su ubuntu. Ora dobbiamo solo sapere perché i build di Ubuntu (e la build di Oracle!) Non impostano la conformità a POSIX2008. Configurare build per altri sistemi operativi o distribuzioni? Quali sono le persone in esecuzione per chi questo codice funziona? Se lo fai in una risposta, lo accetto e grazie! – danarmak

0

sembra essere fissato in java 9

  • Oracle JDK 9.0.4 - Files.getLastModifiedTime dà risoluzione millisecondo
  • Oracle JDK 1.8.162 - Files.getLastModifiedTime dà seconda risoluzione
Problemi correlati