Warm tip: This article is reproduced from stackoverflow.com, please click
java unix nio

Reading Files from JAR (NoSuchFileException)

发布于 2020-03-31 22:56:52

I am trying to read a few files from a JAR file. The JAR file is located in the Tomcat's lib folder. I am reading the file like:

String filePath = DirectoryReader.class.getClassLoader().getResource(directoryPath).getPath();

System.out.println("Directory Path: " + directoryPath);
System.out.println("File Path 1: " + filePath);

filePath = filePath.substring(6, filePath.indexOf("!"));

System.out.println("File Path 2: " + filePath);

Path configJARLocation = Paths.get(filePath);
System.out.println("JAR location: " + configJARLocation.toString());
InputStream inputStream = Files.newInputStream(configJARLocation);
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
InputStreamReader inputStreamReader = null;

But I get an exception in the logs:

Directory Path: META-INF/gmm/xmlFiles/predefined/ipsec/
File Path 1: file:/opt/app/tools/tomcat/lib/appConfigurations.jar!/META-INF/gmm/xmlFiles/predefined/ipsec/
File Path 2: opt/app/tools/tomcat/lib/appConfigurations.jar
JAR location: opt/app/tools/tomcat/lib/appConfigurations.jar
java.nio.file.NoSuchFileException: opt/app/tools/tomcat/lib/appConfigurations.jar
        at sun.nio.fs.UnixException.translateToIOException(UnixException.java:86)
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:102)
        at sun.nio.fs.UnixException.rethrowAsIOException(UnixException.java:107)
        at sun.nio.fs.UnixFileSystemProvider.newByteChannel(UnixFileSystemProvider.java:214)
        at java.nio.file.Files.newByteChannel(Files.java:361)
        at java.nio.file.Files.newByteChannel(Files.java:407)
        at java.nio.file.spi.FileSystemProvider.newInputStream(FileSystemProvider.java:384)
        at java.nio.file.Files.newInputStream(Files.java:152)
        at com.gtc.logicalprovisioning.dac.file.DirectoryReader.process(DirectoryReader.java:72)

Other than the leading / in front of opt, I can't see anything that is incorrect. Line 72 of the code is:

InputStream inputStream = Files.newInputStream(configJARLocation);

The same code is working in Windows. Its only when I deploy on my Unix environment, it starts to fail. I initially thought it was permission or access issue. But doesn't seem to be the case. I changed chmod from 755 first then to 777 for the JAR file. Then I changed the permission using chown. But it still didn't work. I am not a Unix expert, so I cant really dig much into this. Kindly advise! Thanks!

Questioner
hell_storm2004
Viewed
44
hell_storm2004 2020-02-03 16:14

As I said above in my comment.The problem was the file:/ prefix. Since I was doing string manipulation, with the start index of 6, it was causing the first / to get cut from the Unix path.

Windows Path is like:

file:/H:/...

Can't really say why the Windows path has an extra / in front. If anyone can enlighten me on it, that would be nice.

Unix Path is like:

file:/opt/...

So the cleaner option would be the use the URL/URI API to get it done. Should have thought of this earlier, as it is a more graceful way of tackling this.

// JAR File Reading
String filePath = DirectoryReader.class.getClassLoader().getResource(directoryPath).getPath();

filePath = filePath.substring(0, filePath.indexOf("!"));

URL url = new URL(filePath);

Path configJARLocation = Paths.get(url.toURI());

InputStream inputStream = Files.newInputStream(configJARLocation);
ZipInputStream zipInputStream = new ZipInputStream(inputStream);
InputStreamReader inputStreamReader = null;

This worked for me.