Beko
Beko

Reputation: 1002

Specifying generic file path to work with a jar-file

I have a Maven project in which I have a class SomeClass in src/main/java that is supposed to read out a file located in src/main/resources.

This was my first approach:

private static void someMethod() {  
  // ... [context] ...
  String fileName = "src/main/resources/some_file.txt";
  for(String line : Files.readAllLines(Paths.get(fileName))) {
    System.out.println(line);
  }
}

This works fine when run on the Eclipse console, but it doesn't when I execute the jar-file (produced by Maven) on the Windows console (an IOException is thrown).

I thought it'd have to do with the file path, so I changed the code to this:

private static void someMethod() {  
  // ... [context] ...
  String fileName = "C:/Users/.../workspace/.../src/main/resources/some_file.txt";
  for(String line : Files.readAllLines(Paths.get(fileName))) {
    System.out.println(line);
  }
}

This works on both, the Eclipse- and Windows console. But clearly this won't work on another machine.

Upon search I've changed the static method to be non-static, and used ClassLaoder to get the file:

private void someMethod() {
  // ... [context] ...
  ClassLoader cL = getClass().getClassLoader();
  File file = new File(cL.getResource("some_file.txt").getFile());
  for(String line : Files.readAllLines(Paths.get(file.getPath()))) { // or getAbsolutePath()
    System.out.println(line);
  }
}

This one works on the Eclipse console, and when I System.out.println(file.getPath) it prints out the correct path. But it doesn't work on the Windows console. When executing the jar-file, I get this:

Exception in thread "main" java.nio.file.InvalidPathException: Illegal char <:> at index 4: file:\C:\Users\...\target\...-SNAPSHOT.jar!\some_file.txt  
at sun.nio.fs.WindowsPathParser.normalize(Unknown Source)
at sun.nio.fs.WindowsPathParser.parse(Unknown Source)
at sun.nio.fs.WindowsPathParser.parse(Unknown Source)
at sun.nio.fs.WindowsPath.parse(Unknown Source)
at sun.nio.fs.WindowsFileSystem.getPath(Unknown Source)
at java.io.File.toPath(Unknown Source)
...

So, long story cut short: how can I specify the file-path, so that the jar-file produced by the Maven build executes correctly, independent of the platform it's run on?

Upvotes: 3

Views: 1012

Answers (1)

Tunaki
Tunaki

Reputation: 137329

Since you are trying to read from a classpath resource (i.e. a resource that is not in the file system but embedded in a jar, as indicated by src/main/resources), you can't use Files.lines. A Java NIO.2 Path can't be used for a resource inside a JAR.

You need to use an InputStream instead. To read all the lines from a file, you can wrap it into a BufferedReader. Assuming this code is inside the class SomeClass, you could have the following (Java 8):

try (BufferedReader br = new BufferedReader(new InputStreamReader(SomeClass.class.getResourceAsStream("/some_file.txt")))) {
    br.lines().forEach(System.out::println);
}

Upvotes: 6

Related Questions