0
File privateKeyFile = new File(this.getClass().getClassLoader().getResource("privateKey").getFile());

successfully gives me a keyFile. If I now list the path with:

privateKeyFile.toPath()

debug successfully shows me a path to the file:

file:/Users/me/.m2/repository/com/xx/xyz/abc/encryption/1.0/encryption-1.0.jar!/privateKey

--

However, as soon as I try and read that file with

Files.readAllBytes(privateKeyFile.toPath())

I get

Method threw 'java.nio.file.NoSuchFileException' exception.

This is really confusing, and I've tried changing the getResource() to various things like getResource("/privateKey"); - yet that errors a lot sooner, actually a NPE right when trying to create a new File(), so the file MUST exist as I've shown above??

Wayneio
  • 3,466
  • 7
  • 42
  • 73
  • 2
    A file lives on the file system. Your resource is inside a jar file. So it's not a file. Don't use file IO to read resources from the classpath, located inside your jar file, since they are **not** files. If you need a URL, then getResource() gives you that. If you need bytes, then getResourceAsStream() gives you that. – JB Nizet Apr 05 '19 at 13:15
  • @JBNizet I was following this guide https://howtodoinjava.com/java/io/read-file-from-resources-folder/. Can you recommend another? – Wayneio Apr 05 '19 at 13:17
  • No. But the javadoc is your friend. – JB Nizet Apr 05 '19 at 13:20
  • The getFile() method of URL *is not* guaranteed to return a valid file name. It just returns part of a URL, with all the percent-escapes intact. – VGR Apr 05 '19 at 14:36

3 Answers3

1

Thanks to replies, I now use this code successfully

//working
InputStream publicKeyStream = this.getClass().getClassLoader().getResourceAsStream("publicKey");
toByteArray(privateKeyStream));

I initally tried the other method that was given, but that resulted in a BadPaddingException, likely due to not fully reading the file

//The incorrect code:

byte[] array = new byte[in.available()];
in.read(array);
Wayneio
  • 3,466
  • 7
  • 42
  • 73
-1

The constructor of File does not care if the path string actually points to an existing file, so do not rely on that to check whether the file is there or not. Use privateKeyFile.exists() instead (it returns true if the file exists). From what I see, the file really isn't there or the path you give isn't correct, so exists() should return false.

StackLloyd
  • 409
  • 2
  • 9
  • This is not actually correct. File only actually access files that are in the filesystem. The OP is asking to access a file inside of the Jar file, which is a different process. – Fishy Apr 05 '19 at 13:39
  • Indeed it is a different process, but still, nothing prevents you from passing an incorrect path to the File() constructor, as I said. In fact, the problem only arises when you actually try to access said file. What I said is correct, but I understand that I didn't provide a solution. – StackLloyd Apr 05 '19 at 14:07
-3

Since the file is inside of your Jar, it is not recognized by Java as an actual "file". Because of this, you have to read it a little differently. According to this post, you might read it something like this:

InputStream in = getClass().getResourceAsStream("privatekey");

byte[] array = new byte[in.available()];
in.read(array);

Or of you're in Java 9+, it could look like this:

InputStream in = getClass().getResourceAsStream("privatekey"); 
byte[] array = in.readAllBytes();

Edit: Since some people wanted an example with the entire source code of the read function, here you go:

InputStream in = getClass().getResourceAsStream("privatekey"); 

List<Byte> bytes = new ArrayList<Byte>();
while(in.available() > 0) {
    byte[] b = new byte[in.available()];
    in.read(b);
    bytes.addAll(b);
}

byte[] array = (byte[]) bytes.toArray();
Fishy
  • 1,275
  • 1
  • 12
  • 26
  • `available()` doesn't return the total numbers of bytes that ca be read from the stream. Your code is incorrect. It could work, but also could fail readin all the bytes. – JB Nizet Apr 05 '19 at 13:33
  • https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#available() "Returns an estimate of the number of bytes that can be read" – Fishy Apr 05 '19 at 13:35
  • Returns **an estimate** of the number of bytes that can be read (or skipped over) from this input stream **without blocking**. So, it's an estimate, and the estimate is the number of bytes that can be read **without blocking**. So, as I said, it's clearly not the total number of bytes that can be read from the stream. – JB Nizet Apr 05 '19 at 13:36
  • I understand your whole spiel, but this is just an example. It's not the actual implementation. Just trying to explain how it could be read. – Fishy Apr 05 '19 at 13:38
  • And why do you explain it with incorrect code instead of explaining it with correct code, or with no code at all if you can't write it correctly? – JB Nizet Apr 05 '19 at 13:39
  • I don't think you understand that this is a proof of concept. The code is not wrong. It will work just fine, just *might* not read the *entire* file. If the OP chooses to implement it, reading until there are no more bytes to read, so be it. But this code will work, and answers the OP's question. – Fishy Apr 05 '19 at 13:42
  • It **is** clearly wrong. I just pasted the documentation proving that it is wrong. BTW, there is no toByteArray() method either, so the second snippet wouldn't even compile. I don't think you understand that people copy and paste code, and that you just encourage them to introduce buggy code in their code base. – JB Nizet Apr 05 '19 at 13:44
  • As said, "Or of you're in Java 9+": https://docs.oracle.com/javase/9/docs/api/java/io/InputStream.html#readAllBytes-- And what I am doing is answering the OP's question, not writing their entire program for them. Don't encourage people to just ask for other people to write their code for them. I am encouraging actual thinking, and learning. – Fishy Apr 05 '19 at 13:50
  • No, you don't. And don't try to trick me: you deliberately copied a truncated sentence from the javadoc, and now you're claiming that you used readAllBytes() from the beginning, although you used toByteArray(), which doesn't exist: https://stackoverflow.com/posts/55536382/revisions. If you want to encourage thinking, then don't post buggy code. Just tell that you can read the bytes from the returned input stream. I said that in my previous comment: *explaining it with correct code, or with no code at all*. – JB Nizet Apr 05 '19 at 13:55
  • Oh, and the code you posted is extremely inefficient, and incorrect. – JB Nizet Apr 05 '19 at 13:56
  • Hahaha, it's hilarious. Now the OP confirms it copied and pasted your code. So uch for "encouraging actual thinking, and learning". See: I'm quite experienced here. I know that posting incorrect code is never a good idea. Even if you surround it with warnings that it's just a POC. – JB Nizet Apr 05 '19 at 14:02