Can't Access Resources In Executable Jar

前端 未结 4 593
渐次进展
渐次进展 2020-12-07 02:08

Can someone please point out what I\'m doing wrong here.

I have a small weather app that generates and sends an HTML email. With my code below, everything works fin

相关标签:
4条回答
  • 2020-12-07 02:40

    Try this

    new MimeBodyPart().attachFile(new File(this.getClass().getClassLoader().getResource("resources/Cloudy_Day.png").toURI());
    
    0 讨论(0)
  • 2020-12-07 02:49

    Others are correct with the use of getResourceAsStream, but the path is a little tricky. You see the little package icon in the resources folder? That signifies that all the files in the resource folder will be put into the root of the classpath. Just like all the packages in src/main/java are put in the root. So you would take out the resources from the path

    InputStream is = getClass().getResourceAsStream("/Cloudy_Day.png");
    

    An aside: Maven has a file structure conventions. Class path resources are usually put into src/main/resources. If you create a resources dir in the src/main, Eclipse should automatically pick it up, and create the little package icon for a path src/main/resource that you should see in the project explorer. These files would also go to the root and could be accessed the same way. I would fix the file structure to follow this convention.

    Note: A MimeBodyPart, can be Constructed from an InputStream (As suggested by Bill Shannon, this is incorrect). As mentioned in his comment below

    "You can also attach the data using"

    mbp.setDataHandler(new DataHandler(new ByteArrayDataSource(
              this.getClass().getResourceAsStream("/Cloudy_Day.png", "image/png"))));
    
    0 讨论(0)
  • 2020-12-07 02:54

    You can't access resources inside a JAR file as a File, only read them as an InputStream: getResourceAsStream().

    As the MimeBodyPart has no attach() method for an InputStream, the easiest way should be to read your resources and write them to temp files, then attach these files.

    0 讨论(0)
  • 2020-12-07 03:05

    I don't know if this will help anyone or not. But, I have a similar case as the OP and I solved the case by finding the file in the classpath using recursive function. The idea is so that when another developer decided to move the resources into another folder/path. It will still be found as long as the name is still the same.

    For example, in my work we usually put our resources outside the jar, and then we add said resources path into our classpath, so here the classpath of the resources will be different depending on where it is located.

    That's where my code comes to work, no matter where the file is put, as long as it's in the classpath it will be found.

    Here is an example of my code in action:

    import java.io.File;
    
    public class FindResourcesRecursive {
    
        public File findConfigFile(String paths, String configFilename) {
            for (String p : paths.split(File.pathSeparator)) {
                File result = findConfigFile(new File(p), configFilename);
                if (result != null) {
                    return result;
                }
            }
            return null;
        }
    
        private File findConfigFile(File path, String configFilename) {
            if (path.isDirectory()) {
                String[] subPaths = path.list();
                if (subPaths == null) {
                    return null;
                }
                for (String sp : subPaths) {
                    File subPath = new File(path.getAbsoluteFile() + "/" + sp);
                    File result = findConfigFile(subPath, configFilename);
                    if (result != null && result.getName().equalsIgnoreCase(configFilename)) {
                        return result;
                    }
                }
                return null;
            } else {
                File file = path;
                if (file.getName().equalsIgnoreCase(configFilename)) {
                    return file;
                }
                return null;
            }
        }
    
    }
    

    Here I have a test case that is coupled with a file "test.txt" in my test/resources folder. The content of said file is:

    A sample file
    

    Now, here is my test case:

    import org.junit.Test;
    
    import java.io.*;
    
    import static org.junit.Assert.fail;
    
    public class FindResourcesRecursiveTest {
    
        @Test
        public void testFindFile() {
            // Here in the test resources I have a file "test.txt"
            // Inside it is a string "A sample file"
            // My Unit Test will use the class FindResourcesRecursive to find the file and print out the results.
            File testFile = new FindResourcesRecursive().findConfigFile(
                    System.getProperty("java.class.path"),
                    "test.txt"
            );
    
            try (FileInputStream is = new FileInputStream(testFile)) {
                int i;
                while ((i = is.read()) != -1) {
                    System.out.print((char) i);
                }
                System.out.println();
            } catch (IOException e) {
                fail();
            }
    
        }
    }
    

    Now, if you run this test, it will print out "A sample file" and the test will be green.

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