代码之家  ›  专栏  ›  技术社区  ›  M.J.

用Java语言从JAR文件中读取MF文件

  •  25
  • M.J.  · 技术社区  · 14 年前

    有什么方法可以读取JAR文件的内容吗?就像我想读取清单文件以便找到JAR文件和版本的创建者一样。有什么方法可以达到同样的效果吗?

    7 回复  |  直到 6 年前
        1
  •  39
  •   oiavorskyi    14 年前

    下一个代码应该有帮助:

    JarInputStream jarStream = new JarInputStream(stream);
    Manifest mf = jarStream.getManifest();
    

    异常处理留给您:)

        2
  •  34
  •   Brian Pipa    12 年前

    你可以用这样的方法:

    public static String getManifestInfo() {
        Enumeration resEnum;
        try {
            resEnum = Thread.currentThread().getContextClassLoader().getResources(JarFile.MANIFEST_NAME);
            while (resEnum.hasMoreElements()) {
                try {
                    URL url = (URL)resEnum.nextElement();
                    InputStream is = url.openStream();
                    if (is != null) {
                        Manifest manifest = new Manifest(is);
                        Attributes mainAttribs = manifest.getMainAttributes();
                        String version = mainAttribs.getValue("Implementation-Version");
                        if(version != null) {
                            return version;
                        }
                    }
                }
                catch (Exception e) {
                    // Silently ignore wrong manifests on classpath?
                }
            }
        } catch (IOException e1) {
            // Silently ignore wrong manifests on classpath?
        }
        return null; 
    }
    

    要获取清单属性,可以迭代变量“mainattribs”,或者直接检索所需的属性(如果知道键)。

    这段代码循环访问类路径上的每个JAR,并读取每个JAR的清单。如果您知道jar的名称,那么您可能只想查看包含()您感兴趣的jar名称的URL。

        3
  •  30
  •   simpleuser    8 年前

    我建议:

    Package aPackage = MyClassName.class.getPackage();
    String implementationVersion = aPackage.getImplementationVersion();
    String implementationVendor = aPackage.getImplementationVendor();
    

    其中myClassName可以是您编写的应用程序中的任何类。

        4
  •  10
  •   Jake W    11 年前

    我根据StackOverflow的一些想法实现了一个AppVersion类,这里我只分享整个类:

    import java.io.File;
    import java.net.URL;
    import java.util.jar.Attributes;
    import java.util.jar.Manifest;
    
    import org.apache.commons.lang.StringUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    public class AppVersion {
      private static final Logger log = LoggerFactory.getLogger(AppVersion.class);
    
      private static String version;
    
      public static String get() {
        if (StringUtils.isBlank(version)) {
          Class<?> clazz = AppVersion.class;
          String className = clazz.getSimpleName() + ".class";
          String classPath = clazz.getResource(className).toString();
          if (!classPath.startsWith("jar")) {
            // Class not from JAR
            String relativePath = clazz.getName().replace('.', File.separatorChar) + ".class";
            String classFolder = classPath.substring(0, classPath.length() - relativePath.length() - 1);
            String manifestPath = classFolder + "/META-INF/MANIFEST.MF";
            log.debug("manifestPath={}", manifestPath);
            version = readVersionFrom(manifestPath);
          } else {
            String manifestPath = classPath.substring(0, classPath.lastIndexOf("!") + 1) + "/META-INF/MANIFEST.MF";
            log.debug("manifestPath={}", manifestPath);
            version = readVersionFrom(manifestPath);
          }
        }
        return version;
      }
    
      private static String readVersionFrom(String manifestPath) {
        Manifest manifest = null;
        try {
          manifest = new Manifest(new URL(manifestPath).openStream());
          Attributes attrs = manifest.getMainAttributes();
    
          String implementationVersion = attrs.getValue("Implementation-Version");
          implementationVersion = StringUtils.replace(implementationVersion, "-SNAPSHOT", "");
          log.debug("Read Implementation-Version: {}", implementationVersion);
    
          String implementationBuild = attrs.getValue("Implementation-Build");
          log.debug("Read Implementation-Build: {}", implementationBuild);
    
          String version = implementationVersion;
          if (StringUtils.isNotBlank(implementationBuild)) {
            version = StringUtils.join(new String[] { implementationVersion, implementationBuild }, '.');
          }
          return version;
        } catch (Exception e) {
          log.error(e.getMessage(), e);
        }
        return StringUtils.EMPTY;
      }
    }
    

    基本上,这个类可以从它自己的JAR文件清单或者它的classes文件夹中的清单中读取版本信息。希望它能在不同的平台上运行,但到目前为止我只在MacOSX上测试过它。

    我希望这对其他人有用。

        5
  •  3
  •   yegor256    10 年前

    您可以使用实用程序类 Manifests jcabi-manifests :

    final String value = Manifests.read("My-Version");
    

    全班都能找到 MANIFEST.MF 类路径中的可用文件,并从其中一个文件中读取要查找的属性。另外,请阅读: http://www.yegor256.com/2014/07/03/how-to-read-manifest-mf.html

        6
  •  0
  •   BullyWiiPlaza    7 年前

    保持简单。一 JAR 也是一个 ZIP 所以任何 拉链 代码可用于读取 MAINFEST.MF :

    public static String readManifest(String sourceJARFile) throws IOException
    {
        ZipFile zipFile = new ZipFile(sourceJARFile);
        Enumeration entries = zipFile.entries();
    
        while (entries.hasMoreElements())
        {
            ZipEntry zipEntry = (ZipEntry) entries.nextElement();
            if (zipEntry.getName().equals("META-INF/MANIFEST.MF"))
            {
                return toString(zipFile.getInputStream(zipEntry));
            }
        }
    
        throw new IllegalStateException("Manifest not found");
    }
    
    private static String toString(InputStream inputStream) throws IOException
    {
        StringBuilder stringBuilder = new StringBuilder();
        try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)))
        {
            String line;
            while ((line = bufferedReader.readLine()) != null)
            {
                stringBuilder.append(line);
                stringBuilder.append(System.lineSeparator());
            }
        }
    
        return stringBuilder.toString().trim() + System.lineSeparator();
    }
    

    尽管具有灵活性,但仅用于读取数据 this 答案是最好的。

        7
  •  0
  •   Ronald Coarite    6 年前

    以这种简单的方式实现属性

        public static String  getMainClasFromJarFile(String jarFilePath) throws Exception{
        // Path example: "C:\\Users\\GIGABYTE\\.m2\\repository\\domolin\\DeviceTest\\1.0-SNAPSHOT\\DeviceTest-1.0-SNAPSHOT.jar";
        JarInputStream jarStream = new JarInputStream(new FileInputStream(jarFilePath));
        Manifest mf = jarStream.getManifest();
        Attributes attributes = mf.getMainAttributes();
        // Manifest-Version: 1.0
        // Built-By: GIGABYTE
        // Created-By: Apache Maven 3.0.5
        // Build-Jdk: 1.8.0_144
        // Main-Class: domolin.devicetest.DeviceTest
        String mainClass = attributes.getValue("Main-Class");
        //String mainClass = attributes.getValue("Created-By");
        //  Output: domolin.devicetest.DeviceTest
        return mainClass;
    }