[SOLVED] NPE When Accessing Resources Through Jar

Discussion in 'Programming' started by ReadySetPawn, May 24, 2016.

  1. It works fine when I launch my program through my IDE, but when I build the jar and trying executing, it gives me an NPE on the resource file. And yes, I did check to see if my resources are included in the Jar.

    Here's my code:

    Code (Java):
    public static File getFile(String path){
            File file = null;
            path = ("res/" + path).replace("/", File.separator);
            try {
                file = new File(Main.class.getResource(path).toURI());
            } catch (URISyntaxException e){
                e.printStackTrace();
            }
            return file;
        }
    I need a solution ASAP because this is due tomorrow.

    Thanks
     
  2. foncused

    Moderator Patron

    If this only happens when using a .jar, check out your MANIFEST.MF file maybe?

    EDIT: If the NPE is regarding your resource file specifically, check the path?
     
    #2 foncused, May 24, 2016
    Last edited: May 24, 2016
  3. That is not how you access files inside a jar, there are entirely different methods for compressed files. Look it up on stackoverflow.
     
    • Agree Agree x 1
  4. What should I modify in my Manifest.MF?

    I looked all over the internet (even the dreaded second page of Google) and I still couldn't find anything that helped me.
     
  5. <SorakaCare> Let me guide you. </SorakaCare>

    Code (Java):

    public static Schematic LoadJarSchematic(String path)
      {
         RpgLogger.builder("LoadJarSchematic: skylands\\"+path);
         try
         {
           InputStream in = SkyCore.skyplugin.getClass().getClassLoader().getResourceAsStream("skylands\\"+path);
      NBTTagCompound nbtdata = NBTCompressedStreamTools.a(in);
      short width = nbtdata.getShort("Width");
      short height = nbtdata.getShort("Height");
      short length = nbtdata.getShort("Length");
      byte[] blocks = nbtdata.getByteArray("Blocks");
      byte[] data = nbtdata.getByteArray("Data");
      NBTTagList tileentities = nbtdata.getList("TileEntities",10);
      in.close();
      return new Schematic(width,height,length,blocks,data,tileentities,true);
      }
         catch (Exception e)
      {
      e.printStackTrace();
      return new Schematic((short)0,(short)0,(short)0, new byte[0],new byte[0],new NBTTagList(),false);
      }
         //return new Schematic((short)0,(short)0,(short)0, new byte[0],new byte[0],new NBTTagList(),false);
      }
     
  6. How would I be able to do that with .png and .wav files though?
     
  7. He's talking about the ClassLoader#getResourceAsStream call, not the rest of it. That call can be used to get any file from the jar and will solve your problem.
     
  8. Code (Java):
    InputStream in = YourPlugin.getClass().getClassLoader().getResourceAsStream("folderInJar\\"+"FileName.whatever");
    in.readStuff();
    *Spoonfeeding intensifies*
     
  9. Here's my new method:

    Code (Java):

    public static BufferedImage getImage(String path){
        BufferedImage image = null;
        path = ("res/" + path).replace("/", File.separator);
        try {
            image = ImageIO.read(ClassLoader.getSystemClassLoader().getResourceAsStream(path));
        } catch (IOException e){
            e.printStackTrace();
        }
        return image;
    }
        }
    It still doesn't work =/ This time it throws an IllegalArgumentException because it's saying that

    Code (Java):
    ClassLoader.getSystemClassLoader().getResourceAsStream(path)
    is null
     
    #9 ReadySetPawn, May 24, 2016
    Last edited: May 24, 2016
  10. Here is what i use, i believe it works for both the IDE and the jar:

    getClass().getResource("/assets/sounds/" + "MySound" + ".wav")

    So that line would get MySound.wav from inside /assets/sounds/ (Inside the project).
     
  11. Yeah that's what I've been using. It works with the IDE, just not the Jar. Do I have to do something with my project structure?
     
  12. You need to use the plugin classloader (associated with the plugin jar), not the system one.. Just use the exact line of code i gave you.
     
    • Agree Agree x 1
  13. My issue was directly connected to using the / in the beginning of the path. Once i added it, things worked perfectly.
     
  14. I'm not using Bukkit though, I'm just making a simple Java game.

    Hmm, I tried that but I'll try it again and see if it'll help.
     
  15. I've read that thread and managed to come up with this method:

    Code (Java):
    public static BufferedImage getImage(String path){
            BufferedImage image = null;
            path = ("/com/quest/res/" + path).replace("/", File.separator);
            try {
                InputStream in = ClassLoader.getSystemResourceAsStream(path);
                System.out.println(in);
                image = ImageIO.read(ClassLoader.getSystemResourceAsStream(path));
            } catch (IOException e){
                e.printStackTrace();
            }
            return image;
        }
    Still says IllegalArgumentException on the ImageIO line =/
    Thanks for your patience by the way

    P.S. It works on my IDE, just not the Jar still
     
  16. actually READ the thread.. You are just re-using the same nonfunctional code over and over..

    Code (Java):
    InputStream input = getClass().getResourceAsStream("/classpath/to/my/file");
    Are you not sure how to program? You get an instream and then do absolutely nothing with it, and use different, wrong code to try to read...
     
  17. My bad, I completely overlooked the fact that I wasn't using the "in" variable. So what code should I use to try to read it then?
     
  18. Code (Java):
    private void readJar(String path)
       {
         java.io.InputStream istream = getClass().getResourceAsStream(path);
         
         BufferedReader reader = new BufferedReader(new InputStreamReader(istream));
         
         try
         {
           System.out.println(reader.readLine());
         }
         catch (IOException e)
         {
           e.printStackTrace();
         }
       }
    This seems to work.
     
  19. Code (Java):
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStreamReader;
    public class Main
    {
       public static void main(String[] args)
       {
         System.out.println("Attempting to read a file..");
         new Main().readJar("folder/file.txt");
       }
     
       private void readJar(String path)
       {
         java.io.InputStream istream = getClass().getResourceAsStream(path);
       
         BufferedReader reader = new BufferedReader(new InputStreamReader(istream));
       
         try
         {
           System.out.println(reader.readLine());
         }
         catch (IOException e)
         {
           e.printStackTrace();
         }
       }
    }
    Code (Text):

    Microsoft Windows [Version 6.1.7601]
    Copyright (c) 2009 Microsoft Corporation.  All rights reserved.

    C:\Windows\System32>cd C:/Users/Thing/Desktop

    C:\Users\Thing\Desktop>java -jar jarIO.jar
    Attempting to read a file..
    this is some text, and it works.