URI is not hierarchical

Olá… preciso percorrer um diretorio que está dentro do jar, quando rodo pela IDE ele roda normal, quando exporto para jar o seguinte erro é retornado.

Caused by: java.lang.IllegalArgumentException: URI is not hierarchical
        at java.io.File.<init>(Unknown Source)
        at jgf.imaging.loader.DirLoader.load(DirLoader.java:74)
        at jgf.imaging.ImagePallete.reload(ImagePallete.java:102)
        at jgf.imaging.ImagePallete.<init>(ImagePallete.java:51)
        at td.cfg.GameConfig.<clinit>(GameConfig.java:17)
        ... 9 more

O código para carregar é esse:

                             URL resource = getClass().getResource(param.getAttribute("src"));//isso retorna /resource/images
		File file = null;
		try {
			file = new File(resource.toURI());
		} catch (URISyntaxException e1) {
			e1.printStackTrace();
		}
		List<File> files = getAll((file), null);//Aqui listo os arquivos do diretorio

Alguém sabe como resolver esse problema ou percorrer o diretorio de dentro do jar?

tente fazer um método que “saia” da estrutura de navegação do seu JAR e pegue o arquivo “em sí”. Depois, vc navega nele usando os métodos da classe JarFile.

(Eu tenho um método que faz isso, mas infelizmente eu não tenho ele aqui , agora).

Se der um System.out.println(resource), qual a saída (se executado da IDE e do JAR)?

if (uri.isOpaque()) throw new IllegalArgumentException("URI is not hierarchical");
http://java.sun.com/javase/6/docs/api/java/net/URI.html#isOpaque()

Eu já tinha lido isso sobre opaque mas não consegui resolver mesmo assim.

Eu li tambéms obre o scheme que voce colocou o link mas mesmo assim não entendi como vou acessar dentro do jar.

IDE:
file:/D:/softdev/workspace/jse/TD%20Game/bin/resource/images/
Jar:
jar:file:/C:/TDGame.jar!/resource/images/

Pensei em fazer algo assim… mas é que a solução que eu tenho é mais genérica. Mas pelo visto essa é a solução.

Mark, veja essa classe:

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.JarURLConnection;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

public class ImageLoader {

	public Map<String, InputStream> getAll(File file,
			Map<String, InputStream> result) throws IOException {
		if (result == null) {
			result = new HashMap<String, InputStream>();
		}
		if (file.isDirectory()) { // é diretório comum; usa recursividade
			for (File f : file.listFiles()) {
				getAll(f, result);
			}
		} else if (file.getName().endsWith(".png")) { // é um png; adiciona
			result.put(getName(file.getName()), new FileInputStream(file));
		} else if (file.getName().endsWith(".jar")) { // é um jar; vamos
			// brincar!
			JarFile jar = new JarFile(file);
			Enumeration<JarEntry> e = jar.entries();
			while (e.hasMoreElements()) {
				JarEntry entry = e.nextElement();
				if (!entry.isDirectory() && entry.getName().endsWith(".png")) {
					String path = "jar:file://" + file.getAbsolutePath() + "!/"
							+ entry.getName();
					URL url = new URL(path);
					JarURLConnection jarConn = (JarURLConnection) url
							.openConnection();
					String name = entry.getName();
					result.put(getName(name
							.substring(name.lastIndexOf('/') + 1)), jarConn
							.getInputStream());
				}
			}
		}
		return result;
	}

	private String getName(String s) {
		return s.substring(0, s.lastIndexOf("."));
	}

	public static void main(String[] args) throws IOException,
			URISyntaxException {
		ImageLoader il = new ImageLoader();
		URLClassLoader urlLoader = (URLClassLoader) ClassLoader
				.getSystemClassLoader();
		URL[] urls = urlLoader.getURLs();
		System.out.println(il.getAll(new File(urls[0].toURI()), null));
	}

}

Com pequenas mudanças na sua classe original e usando esses métodos acho que resolve.

O resultado do meu teste foi exatamente o mesmo para a IDE e para o JAR. Como você terá o InputStream de cada arquivo “.png” fica fácil carregá-los via ImageIO.

No seu código creio que ficaria algo como:

URLClassLoader urlLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();
URL[] urls = urlLoader.getURLs();
Map<String, InputStream> map = getAll(new File(urls[0].toURI()), null);
for (Entry<String, InputStream> e : map.entrySet()) {
	iml.add(new ImageItem(e.getKey(), ImageIO.read(e.getValue())));
}
java.io.FileNotFoundException: \C\TDGame.jar (O caminho da rede nÒo foi encontr
ado)
        at java.util.zip.ZipFile.open(Native Method)
        at java.util.zip.ZipFile.<init>(Unknown Source)
        at java.util.jar.JarFile.<init>(Unknown Source)
        at java.util.jar.JarFile.<init>(Unknown Source)
        at sun.net.www.protocol.jar.URLJarFile.<init>(Unknown Source)
        at sun.net.www.protocol.jar.URLJarFile.getJarFile(Unknown Source)
        at sun.net.www.protocol.jar.JarFileFactory.get(Unknown Source)
        at sun.net.www.protocol.jar.JarURLConnection.connect(Unknown Source)
        at sun.net.www.protocol.jar.JarURLConnection.getInputStream(Unknown Sour
ce)
        at jgf.imaging.loader.DirLoader.getAll(DirLoader.java:149)
        at jgf.imaging.loader.DirLoader.load(DirLoader.java:90)
        at jgf.imaging.ImagePallete.reload(ImagePallete.java:102)
        at jgf.imaging.ImagePallete.<init>(ImagePallete.java:51)
        at td.cfg.GameConfig.<clinit>

Qual linha é a 149 no seu código?

result.put(getName(name
							.substring(name.lastIndexOf('/') + 1)), jarConn
							.getInputStream());

jarConn.getInputStream

Está retornando isso.

Era para ser:

/* o começo... */name.lastIndexOf(File.separator) // continua...

Esqueci que o separador no Windows é o .

Não… falei besteira. Isso vai resolver o problema do nome, mas não do InputStream.

Antes da linha que dá erro adicione um:

System.out.println(jarConn.getURL());

E poste a saída.

Estou sem tempo agora e resolvi para ele procurar na pasta a partir de onde está o jar. Acredito que agora funcione no linux.

Depois eu vejo isso com mais detalhes por que de qualquer forma eu quero criar um arquivo zipado com as imagens invés do diretorio.

No topico do jogo vou colocar agora essa versao que funciona em linux.

Bom, parece que funciona agora. Mas depois, quanto puder, poste os resultados aqui para tentarmos solucionar. :slight_smile:

Mark_Ameba, qual é a estrutura de diretórios dentro do teu jar?

Se a imagem estiver dentro de resource/images, tenta colocar esse parametro src para resource/imagens, sem o / no começo.

Está /resource/images/
Já tentei com:
“resource/images”
“resource/images/”
“/resource/images”
“/resource/images/”

Isso não resolveu o problema. =/

Opa,

meio tarde pra responder mas uma maneira fácil de resolver este problema é usar

ClassLoader.getSystemResourceAsStream("br/com/pacote/arquivo.txt");

Agora é só ler o InputStream.

Abraço

[quote=brnfd]Opa,

meio tarde pra responder mas uma maneira fácil de resolver este problema é usar

ClassLoader.getSystemResourceAsStream("br/com/pacote/arquivo.txt");

Agora é só ler o InputStream.

Abraço[/quote]

O problema não é esse.

Eu consigo pegar arquivos isolados.

O meu problema é conseguir pegar diretorios de dentro do jar para poder percorre-los e ver todos arquivos dentro dele.