Java 如何列出JAR文件中的文件?
我有一个从目录中读取所有文件的代码Java 如何列出JAR文件中的文件?,java,file,jar,java-io,getresource,Java,File,Jar,Java Io,Getresource,我有一个从目录中读取所有文件的代码 File textFolder = new File("text_directory"); File [] texFiles = textFolder.listFiles( new FileFilter() { public boolean accept( File file ) { return file.getName().endsWith(".txt"); }
File textFolder = new File("text_directory");
File [] texFiles = textFolder.listFiles( new FileFilter() {
public boolean accept( File file ) {
return file.getName().endsWith(".txt");
}
});
它工作得很好。它用目录“text\u directory”中以“.txt”结尾的所有文件填充数组
如何在JAR文件中以类似的方式读取目录的内容
所以我真正想做的是,列出我JAR文件中的所有图像,这样我就可以加载它们了:
ImageIO.read(this.getClass().getResource("CompanyLogo.png"));
(这是因为“CompanyLogo”是“硬编码”的,但是JAR文件中的图像数量可以是10到200个可变长度。)
编辑
所以我想我的主要问题是:如何知道我的主类所在的JAR文件名
当然,我可以使用java.util.Zip
阅读它
我的结构是这样的:
它们是:
my.jar!/Main.class
my.jar!/Aux.class
my.jar!/Other.class
my.jar!/images/image01.png
my.jar!/images/image02a.png
my.jar!/images/imwge034.png
my.jar!/images/imagAe01q.png
my.jar!/META-INF/manifest
现在,我可以使用以下方法加载例如“images/image01.png”:
但这只是因为我知道文件名,其余的我必须动态加载它们。jar文件只是一个带有结构化清单的zip文件。您可以使用常用的JavaZIP工具打开jar文件,并以这种方式扫描文件内容,膨胀流,等等。然后在getResourceAsStream调用中使用它,它应该是完美的 编辑/澄清后 我花了一分钟的时间记住了所有的细节,我确信有更干净的方法来做到这一点,但我想知道我没有疯。在我的项目中,image.jpg是主jar文件的某个部分中的一个文件。我得到了主类的类加载器(SomeClass是入口点),并使用它来发现image.jpg资源。然后用一些流魔法把它放到ImageInputStream中,一切都很好
InputStream inputStream = SomeClass.class.getClassLoader().getResourceAsStream("image.jpg");
JPEGImageReaderSpi imageReaderSpi = new JPEGImageReaderSpi();
ImageReader ir = imageReaderSpi.createReaderInstance();
ImageInputStream iis = new MemoryCacheImageInputStream(inputStream);
ir.setInput(iis);
....
ir.read(0); //will hand us a buffered image
给定一个实际的JAR文件,您可以使用
JarFile.entries()
列出内容。不过,您需要知道JAR文件的位置——您不能只要求类加载器列出它可以得到的所有内容
您应该能够根据从
ThisClassName.class.getResource(“ThisClassName.class”)
返回的URL计算出JAR文件的位置,但这可能有点麻烦。我为“在一个包下运行所有JUnits”编写了一个方法。你应该能够使它适应你的需要
private static void findClassesInJar(List<String> classFiles, String path) throws IOException {
final String[] parts = path.split("\\Q.jar\\\\E");
if (parts.length == 2) {
String jarFilename = parts[0] + ".jar";
String relativePath = parts[1].replace(File.separatorChar, '/');
JarFile jarFile = new JarFile(jarFilename);
final Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
final JarEntry entry = entries.nextElement();
final String entryName = entry.getName();
if (entryName.startsWith(relativePath)) {
classFiles.add(entryName.replace('/', File.separatorChar));
}
}
}
}
private static void findClassesInJar(列出类文件,字符串路径)抛出IOException{
最终字符串[]部分=path.split(\\Q.jar\\\\E”);
如果(parts.length==2){
字符串jarFilename=parts[0]+“.jar”;
字符串relativePath=parts[1]。替换(File.separatorChar,“/”);
JarFile JarFile=新的JarFile(jarFilename);
最终枚举条目=jarFile.entries();
while(entries.hasMoreElements()){
final JarEntry=entries.nextElement();
最后一个字符串entryName=entry.getName();
if(entryName.startsWith(relativePath)){
add(entryName.replace('/',File.separatorChar));
}
}
}
}
编辑:
啊,在这种情况下,您可能也需要这个代码段(相同的用例:)
私有静态文件findClassesDir(类clazz){
试一试{
字符串路径=clazz.getProtectionDomain().getCodeSource().getLocation().getFile();
最终字符串codeSourcePath=URLDecover.decode(路径“UTF-8”);
最后一个字符串thisClassPath=新文件(codeSourcePath,clazz.getPackage().getName().repalce('.',File.separatorChar));
}捕获(不支持的编码异常e){
抛出新断言错误(“不可能”,e);
}
}
注意,在Java7中,您可以从JAR(zip)文件创建一个文件系统
,然后使用NIO的目录遍历和过滤机制进行搜索。这将使编写处理JAR和“分解”目录的代码变得更容易
所以我想我的主要问题是,如何知道我的主类所在的jar的名称
假设您的项目打包在一个Jar中(不一定是真的!),您可以使用ClassLoader.getResource()或findResource()和类名(后跟.class)来获取包含给定类的Jar。您必须从返回的URL解析jar名称(不是那么难),我将留给读者作为练习:-)
确保测试类不是jar的一部分的情况。erickson的工作非常好:
这是工作代码
CodeSource src = MyClass.class.getProtectionDomain().getCodeSource();
List<String> list = new ArrayList<String>();
if( src != null ) {
URL jar = src.getLocation();
ZipInputStream zip = new ZipInputStream( jar.openStream());
ZipEntry ze = null;
while( ( ze = zip.getNextEntry() ) != null ) {
String entryName = ze.getName();
if( entryName.startsWith("images") && entryName.endsWith(".png") ) {
list.add( entryName );
}
}
}
webimages = list.toArray( new String[ list.size() ] );
为此:
String [] webimages = ...
BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex]));
有两个非常有用的实用程序,都称为JarScan:
另请参见此问题:不久前,我制作了一个从JAR内部获取classess的函数:
public static Class[] getClasses(String packageName)
throws ClassNotFoundException{
ArrayList<Class> classes = new ArrayList<Class> ();
packageName = packageName.replaceAll("\\." , "/");
File f = new File(jarName);
if(f.exists()){
try{
JarInputStream jarFile = new JarInputStream(
new FileInputStream (jarName));
JarEntry jarEntry;
while(true) {
jarEntry=jarFile.getNextJarEntry ();
if(jarEntry == null){
break;
}
if((jarEntry.getName ().startsWith (packageName)) &&
(jarEntry.getName ().endsWith (".class")) ) {
classes.add(Class.forName(jarEntry.getName().
replaceAll("/", "\\.").
substring(0, jarEntry.getName().length() - 6)));
}
}
}
catch( Exception e){
e.printStackTrace ();
}
Class[] classesA = new Class[classes.size()];
classes.toArray(classesA);
return classesA;
}else
return null;
}
publicstaticclass[]getClasses(stringpackagename)
抛出ClassNotFoundException{
ArrayList类=新的ArrayList();
packageName=packageName.replaceAll(“\\”,“/”);
文件f=新文件(jarName);
如果(f.exists()){
试一试{
JarInputStream jarFile=新的JarInputStream(
新文件输入流(jarName));
JarEntry-JarEntry;
while(true){
jarEntry=jarFile.getNextJarEntry();
if(jarEntry==null){
打破
}
if((jarEntry.getName().startsWith(packageName))&&
(jarEntry.getName().endsWith(“.class”)){
Class.add(Class.forName(jarEntry.getName())。
全部替换(“/”,“\\”)。
子字符串(0,jarEntry.getName().length()-6));
}
}
}
捕获(例外e){
e、 printStackTrace();
}
Class[]classesA=新类[classes.size()];
类。toArray(类ESA);
返回类a;
}否则
返回null;
}
同时适用于IDE和.jar文件的代码:
import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;
public class ResourceWalker {
public static void main(String[] args) throws URISyntaxException, IOException {
URI uri = ResourceWalker.class.getResource("/resources").toURI();
Path myPath;
if (uri.getScheme().equals("jar")) {
FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
myPath = fileSystem.getPath("/resources");
} else {
myPath = Paths.get(uri);
}
Stream<Path> walk = Files.walk(myPath, 1);
for (Iterator<Path> it = walk.iterator(); it.hasNext();){
System.out.println(it.next());
}
}
}
import java.io.*;
导入java.net。*;
导入java.nio.file.*;
导入java.util.*;
导入java.util
File[] webimages = ...
BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex].getName() ));
String [] webimages = ...
BufferedImage image = ImageIO.read(this.getClass().getResource(webimages[nextIndex]));
public static Class[] getClasses(String packageName)
throws ClassNotFoundException{
ArrayList<Class> classes = new ArrayList<Class> ();
packageName = packageName.replaceAll("\\." , "/");
File f = new File(jarName);
if(f.exists()){
try{
JarInputStream jarFile = new JarInputStream(
new FileInputStream (jarName));
JarEntry jarEntry;
while(true) {
jarEntry=jarFile.getNextJarEntry ();
if(jarEntry == null){
break;
}
if((jarEntry.getName ().startsWith (packageName)) &&
(jarEntry.getName ().endsWith (".class")) ) {
classes.add(Class.forName(jarEntry.getName().
replaceAll("/", "\\.").
substring(0, jarEntry.getName().length() - 6)));
}
}
}
catch( Exception e){
e.printStackTrace ();
}
Class[] classesA = new Class[classes.size()];
classes.toArray(classesA);
return classesA;
}else
return null;
}
import java.io.*;
import java.net.*;
import java.nio.file.*;
import java.util.*;
import java.util.stream.*;
public class ResourceWalker {
public static void main(String[] args) throws URISyntaxException, IOException {
URI uri = ResourceWalker.class.getResource("/resources").toURI();
Path myPath;
if (uri.getScheme().equals("jar")) {
FileSystem fileSystem = FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap());
myPath = fileSystem.getPath("/resources");
} else {
myPath = Paths.get(uri);
}
Stream<Path> walk = Files.walk(myPath, 1);
for (Iterator<Path> it = walk.iterator(); it.hasNext();){
System.out.println(it.next());
}
}
}
URL urlResource = Thead.currentThread().getContextClassLoader().getResource("foo");
JarReader.read(urlResource, new InputStreamCallback() {
@Override
public void onFile(String name, InputStream is) throws IOException {
// got file name and content stream
}
});
Reflections reflections = new Reflections("com.example.package", new ResourcesScanner());
Set<String> paths = reflections.getResources(Pattern.compile(".*\\.template$"));
Map<String, String> templates = new LinkedHashMap<>();
for (String path : paths) {
log.info("Found " + path);
String templateName = Files.getNameWithoutExtension(path);
URL resource = getClass().getClassLoader().getResource(path);
String text = Resources.toString(resource, StandardCharsets.UTF_8);
templates.put(templateName, text);
}
import java.io.IOException;
import java.net.*;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.Collections;
public class ResourceWalker {
public static void main(String[] args) throws URISyntaxException, IOException {
URI uri = ResourceWalker.class.getResource("/resources").toURI();
System.out.println("Starting from: " + uri);
try (FileSystem fileSystem = (uri.getScheme().equals("jar") ? FileSystems.newFileSystem(uri, Collections.<String, Object>emptyMap()) : null)) {
Path myPath = Paths.get(uri);
Files.walkFileTree(myPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
System.out.println(file);
return FileVisitResult.CONTINUE;
}
});
}
}
}
public static ArrayList<String> listItems(String path) throws Exception{
InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(path);
byte[] b = new byte[in.available()];
in.read(b);
String data = new String(b);
String[] s = data.split("\n");
List<String> a = Arrays.asList(s);
ArrayList<String> m = new ArrayList<>(a);
return m;
}
URI mainClasspathElementURI;
try (ScanResult scanResult = new ClassGraph().whitelistPackages("x.y.z")
.enableClassInfo().scan()) {
mainClasspathElementURI =
scanResult.getClassInfo("x.y.z.MainClass").getClasspathElementURI();
}
List<String> classpathElementResourcePaths;
try (ScanResult scanResult = new ClassGraph().overrideClasspath(mainClasspathElementURI)
.scan()) {
classpathElementResourcePaths = scanResult.getAllResources().getPaths();
}