Pregunta

Estoy haciendo un juego en JAVA donde quiero crear una lista de archivos en un directorio determinado en mi jarra para asegurarme de tener una lista de esas clases para usar en el juego.

Por ejemplo, di en mi jar que tengo un directorio

mtd/entity/creep/

Quiero obtener una lista de todos los archivos .class en ese directorio usando código java de otra clase en el jar .

¿Cuál es el mejor código para hacerlo?

¿Fue útil?

Solución

Código java1.4 antiguo, pero eso le daría la idea:

private static List getClassesFromJARFile(String jar, String packageName) throws Error
{
    final List classes = new ArrayList();
    JarInputStream jarFile = null;
    try
    {
        jarFile = new JarInputStream(new FileInputStream(jar));
        JarEntry jarEntry;
        do 
        {       
            try
            {
                jarEntry = jarFile.getNextJarEntry();
            }
            catch(IOException ioe)
            {
                throw new CCException.Error("Unable to get next jar entry from jar file '"+jar+"'", ioe);
            }
            if (jarEntry != null) 
            {
                extractClassFromJar(jar, packageName, classes, jarEntry);
            }
        } while (jarEntry != null);
        closeJarFile(jarFile);
    }
    catch(IOException ioe)
    {
        throw new CCException.Error("Unable to get Jar input stream from '"+jar+"'", ioe);
    }
    finally
    {
        closeJarFile(jarFile);
    }
   return classes;
}
private static void extractClassFromJar(final String jar, final String packageName, final List classes, JarEntry jarEntry) throws Error
{
    String className = jarEntry.getName();
    if (className.endsWith(".class")) 
    {
        className = className.substring(0, className.length() - ".class".length());
        if (className.startsWith(packageName))
        {
            try
            {
                classes.add(Class.forName(className.replace('/', '.')));
            } catch (ClassNotFoundException cnfe)
            {
                throw new CCException.Error("unable to find class named " + className.replace('/', '.') + "' within jar '" + jar + "'", cnfe);
            }
        }
    }
}
private static void closeJarFile(final JarInputStream jarFile)
{
    if(jarFile != null) 
    { 
        try
        {
            jarFile.close(); 
        }
        catch(IOException ioe)
        {
            mockAction();
        }
    }
}

Otros consejos

Probablemente el mejor enfoque es enumerar las clases en tiempo de compilación.

Hay un enfoque de tiempo de ejecución frágil. Lleve su Class ( MyClass.class de this.getClass () ). Llame a getProtectionDomain . Llame a getCodeSource . Llame a getLocation . Llame a openConnection . (Alternativamente, abra un recurso). Transmitir a JarURLConnection . Llame a getJarFile . Llame a entradas . Iterar marcando getName . Realmente no recomiendo este enfoque.

Recuerde que los archivos JAR son solo archivos ZIP renombrados, y es muy fácil leer el contenido de los archivos ZIP en Java:

    File jarName = null;
    try
    {
        jarName = new File (Dir.class.getProtectionDomain().getCodeSource().getLocation().toURI());
    }
    catch (Exception e)
    {
        e.printStackTrace();    
    }

    try 
    {
      ZipFile zf=new ZipFile(jarName.getAbsoluteFile());
      Enumeration e=zf.entries();
      while (e.hasMoreElements()) 
      {
          ZipEntry ze=(ZipEntry)e.nextElement();
          System.out.println(ze.getName());
      }
      zf.close();
   } catch (IOException e) 
   {
      e.printStackTrace();
   }

10 años después de la pregunta, propongo otra forma de hacer el trabajo:

private static void listFilesFromDirectoryInsideAJar(String pathToJar,String directory,String extension) {
        try {
            JarFile jarFile = new JarFile(pathToJar);
            Enumeration<JarEntry> e = jarFile.entries();
            while (e.hasMoreElements()) {
                JarEntry candidat = e.nextElement();
                if (candidat.getName().startsWith(directory) && 
                    candidat.getName().endsWith(extension))
                    LOG.info(candidat.getName());
            }
        } catch (IOException e) {
            LOG.error(e.getMessage(),e);
        }
    }

No es posible, ya que Java no proporciona acceso directo al archivo jar desde el que se cargan las clases. Podría intentar analizar la propiedad del sistema java.class.path para encontrarlo, pero eso no funcionaría en todas las circunstancias. O puede restringir dónde debe residir el archivo jar, o proporcionar la lista de las clases de una manera diferente (por ejemplo, a través del archivo de manifiesto).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top