2

I am getting an NPE at the point of getting path of a File (an sh file in assets folder). I have tried to read about NPE i detail from the following thread, but this actually could not solve my problem.

What is a NullPointerException, and how do I fix it?

Following is my code snippet:

 File absPathofBash;

   url = ClassLoader.class.getResource("assets/forbackingup.sh");
    absPathofBash = new File(url.getPath());

Later I'm using it in a ProcessBuilder, as

ProcessBuilder pb = new ProcessBuilder(url.getPath(), param2, param3)

I've also tried getting the absolute path directly, like

absPathofBash = new File("assets/forbackingup.sh").getAbsolutePath(); 

Using the latter way, I am able to process it, but if I create a jar then the file cannot be found. (although the Jar contains the file within the respective folder assets)

I would be thankful if anyone can help me on that.

Community
  • 1
  • 1
pallavi
  • 23
  • 1
  • 6
  • 4
    You can't use `File` to access embedded resources which are inside the `Jar` file(s), they aren't "files" in the sense that the file system sees them, they a bunch of compressed bytes inside a zip file (essentially). In your case, if you want to execute the file, you will need to extract the file from the Jar file (you can use `Class#getResourceAsStream`) and then execute it – MadProgrammer Oct 16 '15 at 06:53

5 Answers5

2

Once you have packaged your code as a jar, you can not load files that are inside the jar using file path, instead they are class resources and you have to use this to load:

this.getClass().getClassLoader().getResource("assets/forbackingup.sh");

This way you load assets/forbackingup.sh as an absolute path inside your jar. you also can use this.getClass().getResource() but this way the path must be relative to this class path inside jar.

getResource method gives you an URL, if you want to get directly an InputStream you can use getResourceAsStream

Hope it helps!

malaguna
  • 4,183
  • 1
  • 17
  • 33
  • And how can I pipe the InputStream in ProcessBuilder ? – pallavi Oct 16 '15 at 09:45
  • `ProcessBuilder` is meant to create operative system processes that usually you run as commands with args list. Thus, you can not run a shell script that are inside a jar. If you want to do that, I think you have to create a temp file from the `InputStream` and then use this tmpFile to go on `ProcessBuilder`. – malaguna Oct 16 '15 at 09:52
  • I have already got this working, i.e., executing a shell script through a jar. Where I got stuck is, the time I tried executing this jar directly without changing the current directory in the terminal. If I **cd** to the jar's directory, and then execute this jar file, it works perfectly. But otherwise (as per my requirement) it is not able to locate my **sh file**. – pallavi Oct 16 '15 at 09:58
  • I realised this was a stupid ques, read inputstream in a file, and later the filepath into the ProcessBuilder. – pallavi Oct 17 '15 at 04:08
0

Since the file itself is in the jar file, you could try using:

InputStream is = this.getClass().getClassLoader().getResourceAsStream(fileNameFromJar);
Jeevan Patil
  • 6,029
  • 3
  • 33
  • 50
0

In case of jar file , classloader will return URL different than that of when the target file is not embedded inside jar. Refer to answer on link which should help u : How to use ClassLoader.getResources() in jar file

Community
  • 1
  • 1
vishal
  • 32
  • 2
  • 8
0

I got it done by creating a temp file. Though it's not difficult, yet I'm posting the code patch here:

InputStream stream = MyClass.class.getClassLoader().
            getResourceAsStream("assets/forbackingup.sh");

        File temp = File.createTempFile("forbackingup", ".sh");



      OutputStream outputStream =   
               new FileOutputStream(temp);

      int read = 0;

      byte[] bytes = new byte[1024];

      while ((read = stream.read(bytes)) != -1) {

            outputStream.write(bytes, 0, read);
            outputStream.close();

      }

Now, we have this temp file here which we can pipe to the ProcessBuilder like,

String _filePath=temp.getPath();
ProcessBuilder pb = new ProcessBuilder(url.getPath(), param2, param3)

Thank you everyone for your considerations.

pallavi
  • 23
  • 1
  • 6
-1

You can use Path class like :

Path path = Paths.get("data/test-write.txt");
if(!Files.exists(path)){
    // can handle null pointer exception
}
  • 1
    While this may theoretically answer the question, it's not really a good answer, since it doesn't teach the OP. Instead it gives an alternative solution without explanation. This will usually lead to OP not learning, and coming back for asking a new question when a similar problem occurs. Would you mind adding some explanation? – Vogel612 Oct 16 '15 at 10:37