使用 Java 读取 .jar 清单文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19347052/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using Java to read a .jar manifest file
提问by Kyle
so I am trying to see if a .jar is valid or not, by checking some values in the mainfest file. What is the best way to read and parse the file using java? I thought of using this command to extract the file
所以我试图通过检查 mainfest 文件中的一些值来查看 .jar 是否有效。使用java读取和解析文件的最佳方法是什么?我想到了用这个命令来解压文件
jar -xvf anyjar.jar META-INF/MANIFEST.MF
But can I just do something like:
但我可以做一些类似的事情:
File manifest = Command.exec("jar -xvf anyjar.jar META-INF/MAINFEST.MF");
Then use some buffered reader or something to parse the lines of the file?
然后使用一些缓冲阅读器或其他东西来解析文件的行?
Thanks for any help...
谢谢你的帮助...
采纳答案by Robin Green
The problem with using the jar
tool is that it requires the full JDK to be installed. Many users of Java will only have the JRE installed, which does not include jar
.
使用该jar
工具的问题在于它需要安装完整的 JDK。许多 Java 用户只会安装 JRE,其中不包括jar
.
Also, jar
would have to be on the user's PATH.
此外,jar
必须在用户的 PATH 上。
So instead I would recommend using the proper API, like this:
因此,我建议使用正确的 API,如下所示:
Manifest m = new JarFile("anyjar.jar").getManifest();
That should actually be easier!
那实际上应该更容易!
回答by Iceberg
The Package class at java.lang.Packagehas methods to do what you want. Here is an easy way to get manifest contents using your java code:
java.lang.Package 中的 Package 类具有执行您想要的操作的方法。这是使用 Java 代码获取清单内容的简单方法:
String t = this.getClass().getPackage().getImplementationTitle();
String v = this.getClass().getPackage().getImplementationVersion();
I put this into a static method in a shared utility class.The method accepts a class handle object as a parameter. This way, any class in our system can get their own manifest information when they need it. Obviously the method could be easily modified to return an array or hashmap of values.
我把它放到一个共享实用程序类中的静态方法中。该方法接受一个类句柄对象作为参数。这样,我们系统中的任何类都可以在需要时获取自己的清单信息。显然,可以轻松修改该方法以返回值的数组或哈希图。
call the method:
调用方法:
String ver = GeneralUtils.checkImplVersion(this);
the method in a file called GeneralUtils.java:
名为GeneralUtils.java的文件中的方法:
public static String checkImplVersion(Object classHandle)
{
String v = classHandle.getClass().getPackage().getImplementationVersion();
return v;
}
And to get manifest fields-values other than those you can get via the Package class (e.g. your own Build-Date), you get the Main Attibutes and work through those, asking for the particular one you want. This following code is a slight mod from a similar question I found, probably here on SO. (I would like to credit it but I lost it - sorry.)
并且要获得清单字段值,而不是您可以通过 Package 类获得的值(例如您自己的 Build-Date),您可以获取 Main Attibutes 并处理这些值,询问您想要的特定属性。下面的代码是我发现的一个类似问题的轻微修改,可能在这里。(我想归功于它,但我失去了它 - 抱歉。)
put this in a try-catch block, passing in a classHandle (the "this" or MyClass.class ) to the method. "classHandle" is of type Class:
将其放在 try-catch 块中,将 classHandle(“this”或 MyClass.class )传递给该方法。“classHandle”是类类型:
String buildDateToReturn = null;
try
{
String path = classHandle.getProtectionDomain().getCodeSource().getLocation().getPath();
JarFile jar = new JarFile(path); // or can give a File handle
Manifest mf = jar.getManifest();
final Attributes mattr = mf.getMainAttributes();
LOGGER.trace(" --- getBuildDate: "
+"\n\t path: "+ path
+"\n\t jar: "+ jar.getName()
+"\n\t manifest: "+ mf.getClass().getSimpleName()
);
for (Object key : mattr.keySet())
{
String val = mattr.getValue((Name)key);
if (key != null && (key.toString()).contains("Build-Date"))
{
buildDateToReturn = val;
}
}
}
catch (IOException e)
{ ... }
return buildDateToReturn;
回答by ayurchuk
The easiest way is to use JarURLConnection class :
最简单的方法是使用 JarURLConnection 类:
String className = getClass().getSimpleName() + ".class";
String classPath = getClass().getResource(className).toString();
if (!classPath.startsWith("jar")) {
return DEFAULT_PROPERTY_VALUE;
}
URL url = new URL(classPath);
JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
Manifest manifest = jarConnection.getManifest();
Attributes attributes = manifest.getMainAttributes();
return attributes.getValue(PROPERTY_NAME);
Because in some cases ...class.getProtectionDomain().getCodeSource().getLocation();
gives path with vfs:/
, so this should be handled additionally.
因为在某些情况下...class.getProtectionDomain().getCodeSource().getLocation();
给出了路径vfs:/
,所以这应该额外处理。
Or, with ProtectionDomain:
或者,使用 ProtectionDomain:
File file = new File(getClass().getProtectionDomain().getCodeSource().getLocation().toURI());
if (file.isFile()) {
JarFile jarFile = new JarFile(file);
Manifest manifest = jarFile.getManifest();
Attributes attributes = manifest.getMainAttributes();
return attributes.getValue(PROPERTY_NAME);
}