How to load a folder from a .jar?

前端 未结 4 2110
广开言路
广开言路 2020-12-01 15:07

OK. So I have a pretty simple question: I want to be able to load a resource (a whole folder) from inside a running .jar file, but I have not been able to get it to work. Th

相关标签:
4条回答
  • 2020-12-01 15:48

    It's pretty simple:

    getClass().getResourceAsStream("/resources/images/myImage.png")
    

    Would return an input stream which can be used like so:

    Image myImage = ImageIO.read(getClass().getResourceAsStream("/resources/images/myImage.png"));
    

    And from there, use your Image how you like. This also works just as well if you're using the input stream to read a text file, or for pretty much whatever else you're doing.

    Edit: The path above is relative to the .jar's root.

    0 讨论(0)
  • 2020-12-01 15:51

    Up until now (December 2017), this is the only solution I found which works both inside and outside the IDE (Using PathMatchingResourcePatternResolver): https://stackoverflow.com/a/47904173/6792588

    0 讨论(0)
  • 2020-12-01 16:02

    I think I am on to something. In Eclipse, make a new source folder named "resources" and in that folder, create a package named "myFolder". To have a Path to "myFolder", you just have to say:

    Path path = Paths.get(Main.class.getResource("/myFolder").toURI()); // or the class name instead of Main
    
    0 讨论(0)
  • 2020-12-01 16:04

    There's no way this will work. You're trying to create a File object from a resource inside a JAR. That isn't going to happen. The best method to load resources is to make one your package folders a resource folder, then make a Resources.jar in it or something, dump your resources in the same dir, and then use Resources.class.getResourceAsStream(resFileName) in your other Java class files.

    If you need to 'brute force' the subfiles in the JAR directory pointed to by the URL given by getResource(..), use the following (although it's a bit of a hack!). It will work for a normal filesystem too:

      /**
       * List directory contents for a resource folder. Not recursive.
       * This is basically a brute-force implementation.
       * Works for regular files and also JARs.
       * 
       * @author Greg Briggs
       * @param clazz Any java class that lives in the same place as the resources you want.
       * @param path Should end with "/", but not start with one.
       * @return Just the name of each member item, not the full paths.
       * @throws URISyntaxException 
       * @throws IOException 
       */
      String[] getResourceListing(Class clazz, String path) throws URISyntaxException, IOException {
          URL dirURL = clazz.getClassLoader().getResource(path);
          if (dirURL != null && dirURL.getProtocol().equals("file")) {
            /* A file path: easy enough */
            return new File(dirURL.toURI()).list();
          } 
    
          if (dirURL == null) {
            /* 
             * In case of a jar file, we can't actually find a directory.
             * Have to assume the same jar as clazz.
             */
            String me = clazz.getName().replace(".", "/")+".class";
            dirURL = clazz.getClassLoader().getResource(me);
          }
    
          if (dirURL.getProtocol().equals("jar")) {
            /* A JAR path */
            String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
            JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
            Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
            Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
            while(entries.hasMoreElements()) {
              String name = entries.nextElement().getName();
              if (name.startsWith(path)) { //filter according to the path
                String entry = name.substring(path.length());
                int checkSubdir = entry.indexOf("/");
                if (checkSubdir >= 0) {
                  // if it is a subdirectory, we just return the directory name
                  entry = entry.substring(0, checkSubdir);
                }
                result.add(entry);
              }
            }
            return result.toArray(new String[result.size()]);
          } 
    
          throw new UnsupportedOperationException("Cannot list files for URL "+dirURL);
      }
    

    You can then modify the URL given by getResource(..) and append the file on the end, and pass these URLs into getResourceAsStream(..), ready for loading. If you didn't understand this, you need to read up on classloading.

    0 讨论(0)
提交回复
热议问题