【问题标题】:How do I get the last modification time of a Java resource?如何获取 Java 资源的最后修改时间?
【发布时间】:2011-01-04 16:01:38
【问题描述】:

谁能告诉我一个可靠的方法来获取 Java 资源的最后修改时间?资源可以是文件或 JAR 中的条目。

【问题讨论】:

  • 我什至不知道 JAR 中可能有时间戳,但鉴于它就像 ZIP,我并不完全感到惊讶。很有趣。
  • @Amigable Clark Kant - 只是一个注释,但 JAR 格式将在 Java 7 中得到更新,因此关于它是 ZIP 文件的假设可能不再成立。
  • Java 8 中仍然存在 :)

标签: java resources last-modified


【解决方案1】:

如果你用“资源”表示可以通过 Class#getResource 或 ClassLoader#getResource 访问的东西,你可以通过 URLConnection 获取最后修改的时间戳:

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

请注意,如果上次修改时间未知,getLastModified() 将返回 0,遗憾的是,这与读取“1970 年 1 月 1 日 0:00 UTC”的真实时间戳无法区分。

【讨论】:

  • 适用于 Swing,但不适用于 Android。在 Android 中,我总是得到 0,尽管可访问的 jarfile 有一个非零的最后修改日期。
  • @j4nbur53:您正在编译的 JAR 文件?那个在运行时不可用。不知道时间戳是否保留在 Android APK 文件中。即使语言相似,Android 运行时与 Java 运行时也有很大不同。
  • Android 上的 APK 文件也是一个 JAR 文件,您可以通过简单的 getResource() 调用获取条目的 URL。但是 Android 上的实现不同于 Swing 上的实现。 JarURLConnection 没有通过委托给底层 jar 文件来实现 getHeader() ,因此最终它在 Android 上不起作用。 (可以检查两个来源并找出实现的差异)
  • "不幸的是,这无法与真正的时间戳区分开来" 除非您有一些 非常 旧文件放在周围,否则我认为很难区分真正的最后一个-修改日期和 1970 年 1 月 1 日 :)
  • @jarnbjo 是的。但在实践中,这很少成为问题。不过有一个优势......这个神奇的 EPOCH 日期允许我在我不想提供个人详细信息的网站上填写 1/1/1970 作为生日,安全地知道在数据库中只有 @987654323 的值@ :)
【解决方案2】:

url.openConnection().getLastModified() 的问题在于 FileURLConnection 上的getLastModified() 为该文件创建了一个 InputStream。因此,您必须在获得最后修改日期后致电urlConnection.getInputStream().close()。相反,JarURLConnection 在调用 getInputStream() 时创建输入流。

【讨论】:

  • 那么让它打开或调用 getinputstream 然后关闭哪个更优化?
  • @nullsector76 让流保持打开状态总是会导致资源泄漏。只能使用不打开任何流的api进行优化。
【解决方案3】:

Apache Commons VFS 提供了一种与from different sources 文件交互的通用方式。 FileObject.getContent() 返回一个 FileContent 对象,该对象具有 retreiving the last modified time 的方法。

这是来自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());
}

【讨论】:

  • 听起来过于复杂。我最后使用了 java zip api,然后使用了最后修改的。我还对它们进行了迭代,然后比较了修改后的罐子中最有可能未修改的邮票。
【解决方案4】:

我目前正在使用以下解决方案。解决方案是 与最初步骤中的大多数其他解决方案一样,即 一些 getResource(),然后是 openConnection()。

但是当我有连接时,我使用以下代码:

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

上面的代码适用于安卓和非安卓,它返回 如果资源是,则 ZIP 内条目的最后修改日期 在档案中找到,否则它返回它从中获得的内容 连接。

再见

P.S.:代码还需要刷一些,有一些边框 getJarEntry() 为空的情况。

【讨论】:

    【解决方案5】:

    这是我获取 JAR 文件或编译类的最后修改时间的代码(使用 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);
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2012-11-07
      • 1970-01-01
      • 2011-12-09
      • 1970-01-01
      • 1970-01-01
      • 2011-11-11
      • 1970-01-01
      • 1970-01-01
      • 2010-10-05
      相关资源
      最近更新 更多