2013-08-05 23 views
38

Mam pliki w folderze zasobów. Na przykład, jeśli trzeba uzyskać plik z folderu zasobów, robię tak:Dlaczego mój URI nie jest hierarchiczny?

File myFile= new File(MyClass.class.getResource(/myFile.jpg).toURI());    
System.out.println(MyClass.class.getResource(/myFile.jpg).getPath()); 

Mam przetestowany wszystko działa!

Ścieżka jest

/D:/java/projects/.../classes/X/Y/Z/myFile.jpg

Ale, Jeśli utworzyć plik jar, używania, Maven:

mvn package 

... a następnie uruchomić mój app:

java -jar MyJar.jar 

że mam następujący błąd:

Exception in thread "Thread-4" java.lang.RuntimeException: ხელმოწერის განხორციელება შეუძლებელია 
Caused by: java.lang.IllegalArgumentException: URI is not hierarchical 
     at java.io.File.<init>(File.java:363) 

... i ścieżki pliku jest:

file:/D:/java/projects/.../target/MyJar.jar!/X/Y/Z/myFile.jpg 

Ten wyjątek dzieje, gdy próbuję uzyskać plik z folderu zasobów. W tej linii. Czemu? Dlaczego ten problem występuje w pliku JAR? Co myślisz?

Czy istnieje inny sposób uzyskania ścieżki do folderu zasobów?

+4

Możesz rzucić okiem na to: http://stackoverflow.com/questions/10144210/java-jar-file-use-resource-errors-uri-is-not-hierarchical i zaakceptowana odpowiedź. – cyroxx

Odpowiedz

57

Należy używać

getResourceAsStream(...); 

gdy zasób jest spakowany jako słoik/wojny lub jakiegokolwiek innego pakietu pojedynczy plik o to chodzi.

Zobacz, że słoik to pojedynczy plik (coś w rodzaju pliku zip), który zawiera wiele plików razem. Z pogoka Os, pojedynczego pliku i jeśli chcesz uzyskać dostęp do part of the file (twój plik obrazu), musisz użyć go jako strumienia.

Documentation

10

Oto rozwiązanie dla Eclipse RCP/twórców wtyczek:

Bundle bundle = Platform.getBundle("resource_from_some_plugin"); 
URL fileURL = bundle.getEntry("files/test.txt"); 
File file = null; 
try { 
    URL resolvedFileURL = FileLocator.toFileURL(fileURL); 

    // We need to use the 3-arg constructor of URI in order to properly escape file system chars 
    URI resolvedURI = new URI(resolvedFileURL.getProtocol(), resolvedFileURL.getPath(), null); 
    File file = new File(resolvedURI); 
} catch (URISyntaxException e1) { 
    e1.printStackTrace(); 
} catch (IOException e1) { 
    e1.printStackTrace(); 
} 

To bardzo ważne, aby użyć FileLocator.toFileURL(fileURL) zamiast resolve(fileURL) , bo gdy wtyczka jest pakowany w słoik spowoduje to Eclipse, aby utworzyć rozpakowaną wersję w tymczasowej lokalizacji, aby umożliwić dostęp do obiektu za pomocą pliku. Na przykład, myślę, że Lars Vogel ma błąd w swoim artykule - http://blog.vogella.com/2010/07/06/reading-resources-from-plugin/

+3

Dziękuję, jestem ci winien za to piwo, w rzeczy samej artykuł Vogelli wymaga aktualizacji. –

+0

@Vladllie Miłość, która ci pomogła ;-) –

+0

http://help.eclipse.org/indigo/index.jsp?topic=%2Forg.eclipse.platform.doc.isv%2Freference%2Fapi%2Forg%2Feclipse%2Fcore % 2Fruntime 2 2FFileLocator.html To rozwiązanie wydaje się być zależne od platformy. Czy istnieje sposób na osiągnięcie czegoś podobnego z IntelliJ bez konieczności importowania "org.eclipse.core.runtime.FileLocator"? – Kwoinkwoin

0

Mam do czynienia z tym samym problemem, gdy pracowałem nad projektem w mojej firmie. Przede wszystkim URI nie jest hierarychalny Problem polega na tym, że prawdopodobnie używasz "/" jako seperatora plików.

Musisz pamiętać, że "/" jest dla Windows i z OS na OS zmienia się. Może się różnić w Linuksie. W związku z tym użyj opcji File.seperator.

Więc za pomocą

this.getClass().getClassLoader().getResource("res"+File.seperator+"secondFolder") 

może usunąć URI nie hierarichal. Ale teraz możesz napotkać wyjątek wyjątku zerowego. Próbowałem na wiele różnych sposobów, a następnie użyłem klasy JarEntries, aby ją rozwiązać.

File jarFile = new File(this.getClass().getProtectionDomain().getCodeSource().getLocation().toURI().getPath()); 
     String actualFile = jarFile.getParentFile().getAbsolutePath()+File.separator+"Name_Of_Jar_File.jar"; 
     System.out.println("jarFile is : "+jarFile.getAbsolutePath()); 
     System.out.println("actulaFilePath is : "+actualFile); 
     final JarFile jar = new JarFile(actualFile); 
     final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar 
     System.out.println("Reading entries in jar file "); 
     while(entries.hasMoreElements()) { 
      JarEntry jarEntry = entries.nextElement(); 
      final String name = jarEntry.getName(); 
      if (name.startsWith("Might Specify a folder name you are searching for")) { //filter according to the path 
       System.out.println("file name is "+name); 
       System.out.println("is directory : "+jarEntry.isDirectory()); 
       File scriptsFile = new File(name); 
       System.out.println("file names are : "+scriptsFile.getAbsolutePath()); 

      } 
     } 
     jar.close(); 

Należy tutaj wyraźnie podać nazwę jar. Więc Użyj tego kodu, to da ci katalog i podkatalog wewnątrz folderu w słoiku.

Powiązane problemy