2010-01-13 18 views
11

¿Puede alguien decirme una forma confiable de obtener la última modificación de un recurso de Java? El recurso puede ser un archivo o una entrada en un JAR.¿Cómo obtengo la última modificación de un recurso de Java?

+0

Ni siquiera sabía que los JAR podrían tener marcas de tiempo en ellos, pero dado que es como un ZIP, no estoy del todo sorprendido. Interesante. –

+0

@Amigable Clark Kant: solo una nota, pero el formato JAR recibirá una actualización con Java 7, por lo que las suposiciones de que se trata de un archivo ZIP pueden no ser válidas. – McDowell

+0

Aún se conservan en Java 8 :) –

Respuesta

16

Si con "recurso" decir algo alcanzable a través de la clase nº getResource o cargador de clases # getResource, se puede obtener la última marca de tiempo modificado a través de la URLConnection:

URL url = Test.class.getResource("/org/jdom/Attribute.class"); 
System.out.println(new Date(url.openConnection().getLastModified())); 

Sé consciente de que getlastmodified() devuelve 0 si se desconoce la última modificación, que desafortunadamente es imposible de distinguir de una lectura de marca de tiempo real "1 de enero de 1970, 0:00 UTC".

+0

Consulte la respuesta de cornz para ver un error en el código anterior. –

+0

Funciona en Swing, pero no en Android. En Android siempre obtengo 0, aunque el archivo jar accesible tiene una fecha de modificación distinta de cero. –

+0

@ j4nbur53: ¿El archivo JAR contra el que está compilando? Ese no está disponible en tiempo de ejecución. No tengo idea de si la marca de tiempo se conserva en el archivo APK de Android. Incluso si el lenguaje es similar, el tiempo de ejecución de Android es muy diferente del tiempo de ejecución de Java. – jarnbjo

4

Apache Commons VFS proporciona un genérico forma de interactuar con los archivos from different sources. FileObject.getContent() devuelve un objeto FileContent que tiene un método para retreiving the last modified time.

Aquí es un ejemplo modificado de la VFS website:

import org.apache.commons.vfs.FileSystemManager; 
import org.apache.commons.vfs.FileObject; 
... 
FileSystemManager fsManager = VFS.getManager(); 
FileObject jarFile = fsManager.resolveFile("jar:lib/aJarFile.jar"); 
System.out.println(jarFile.getName().getBaseName() + " " + jarFile.getContent().getLastModifiedTime()); 

// List the children of the Jar file 
FileObject[] children = jarFile.getChildren(); 
System.out.println("Children of " + jarFile.getName().getURI()); 
for (int i = 0; i < children.length; i++) 
{ 
    System.out.println(children[ i ].getName().getBaseName() + " " + children[ i ].getContent().getLastModifiedTime()); 
} 
5

El problema es que url.openConnection().getLastModified()getLastModified() en un FileURLConnection crea un InputStream a ese archivo. Entonces debe llamar al urlConnection.getInputStream().close() después de obtener la fecha de la última modificación. Por el contrario, JarURLConnection crea la secuencia de entrada al llamar a getInputStream().

2

Actualmente estoy usando la siguiente solución. La solución es la igual que la mayoría de las otras soluciones en sus pasos iniciales, es decir, algunos getResource() y luego openConnection().

Pero cuando tengo la conexión que estoy usando el siguiente código:

/** 
* <p>Retrieve the last modified date of the connection.</p> 
* 
* @param con The connection. 
* @return The last modified date. 
* @throws IOException Shit happens. 
*/ 
private static long getLastModified(URLConnection con) throws IOException { 
    if (con instanceof JarURLConnection) { 
     return ((JarURLConnection)con).getJarEntry().getTime(); 
    } else { 
     return con.getLastModified(); 
    } 
} 

El código anterior funciona en Android y no androide, que devuelve el última fecha de modificación de la entrada dentro de la postal si el recursos es encontrado dentro de un archivo, de lo contrario devuelve lo que obtiene de la conexión.

adiós

P.S .: El código todavía necesita un poco de cepillado, hay algunos casos en los que la frontera getJarEntry() es nulo.

1

Aquí está mi código para obtener la última modificación de tiempo de su archivo JAR o clase compilada (cuando se usa un IDE).

import java.io.File; 
import java.io.IOException; 
import java.net.URISyntaxException; 
import java.net.URL; 
import java.nio.file.attribute.FileTime; 
import java.text.DateFormat; 
import java.util.Date; 
import java.util.Enumeration; 
import java.util.Locale; 
import java.util.jar.JarEntry; 
import java.util.jar.JarFile; 
import java.util.zip.ZipEntry; 

public class ProgramBuildTime 
{ 
    private static String getJarName() 
    { 
     Class<?> currentClass = getCurrentClass(); 
     return new File(currentClass.getProtectionDomain() 
       .getCodeSource() 
       .getLocation() 
       .getPath()) 
       .getName(); 
    } 

    private static Class<?> getCurrentClass() 
    { 
     return new Object() {}.getClass().getEnclosingClass(); 
    } 

    private static boolean runningFromJAR() 
    { 
     String jarName = getJarName(); 
     return jarName.endsWith(".jar"); 
    } 

    public static String getLastModifiedDate() throws IOException, URISyntaxException 
    { 
     Date date; 

     if (runningFromJAR()) 
     { 
      String jarFilePath = getJarName(); 
      try (JarFile jarFile = new JarFile(jarFilePath)) 
      { 
       long lastModifiedDate = 0; 

       for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) 
       { 
        String element = entries.nextElement().toString(); 
        ZipEntry entry = jarFile.getEntry(element); 
        FileTime fileTime = entry.getLastModifiedTime(); 
        long time = fileTime.toMillis(); 

        if (time > lastModifiedDate) 
        { 
         lastModifiedDate = time; 
        } 
       } 

       date = new Date(lastModifiedDate); 
      } 
     } else 
     { 
      Class<?> currentClass = getCurrentClass(); 
      URL resource = currentClass.getResource(currentClass.getSimpleName() + ".class"); 

      switch (resource.getProtocol()) 
      { 
       case "file": 
        date = new Date(new File(resource.toURI()).lastModified()); 
        break; 

       default: 
        throw new IllegalStateException("No matching protocol found!"); 
      } 
     } 

     DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.SHORT, Locale.US); 
     return dateFormat.format(date); 
    } 
} 
Cuestiones relacionadas