Search code examples
javajavafx-8

File not found When it's there


For some reason (new to Java), when I'm trying to read an Excel file from my resources folder, it shows that it is there, but when I use FileInputStream to read it I get a FileNotFound Exception. Any ideas?

Code:

public static void openExcelSheet() throws IOException {
    FileInputStream fileInputStream = null;
    if(applicationSettings.class.getResourceAsStream("/files/Employees.xlsx") != null) {
        System.out.println("File Found");
        fileInputStream = new FileInputStream("/files/Employees.xlsx");
    }else {
        System.out.println("File Not Found");
    }

    XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);

    //int numberOfSheets = workbook.getNumberOfSheets();
    System.out.println(workbook.getAllNames());

    workbook.close();
}

Here is the Output that I am receiving:

File Found
Exception in Application start method
java.lang.reflect.InvocationTargetException
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:473)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:372)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:941)
Caused by: java.lang.RuntimeException: Exception in Application start method
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:973)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:198)
	at java.base/java.lang.Thread.run(Thread.java:844)
Caused by: java.io.FileNotFoundException: /files/Employees.xlsx (No such file or directory)
	at java.base/java.io.FileInputStream.open0(Native Method)
	at java.base/java.io.FileInputStream.open(FileInputStream.java:220)
	at java.base/java.io.FileInputStream.<init>(FileInputStream.java:158)
	at java.base/java.io.FileInputStream.<init>(FileInputStream.java:113)
	at applicationSettings.openExcelSheet(applicationSettings.java:32)
	at loginScreen.start(loginScreen.java:70)
	at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:919)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$11(PlatformImpl.java:449)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$9(PlatformImpl.java:418)
	at java.base/java.security.AccessController.doPrivileged(Native Method)
	at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:417)
	at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
Exception running application loginScreen


Solution

  • The problem seems to be some incorrect assumptions in your code:

    if (applicationSettings.class.getResourceAsStream("/files/Employees.xlsx") != null) {
        System.out.println("File Found");
        fileInputStream = new FileInputStream("/files/Employees.xlsx");
    } else {
        System.out.println("File Not Found");
    }
    

    So this is saying: "if I can find "Employees.xlsx" on the resource path, I can find it in the file system with the same path".

    There are two incorrect assumptions here:

    1. You are assuming that since you found "Employees.xlsx" on the resource path will be in the file system at all. This is not a valid assumption:

      • The resource could be (in fact, typically will be) a member of a JAR file or a similar file.
      • The resource or the resource's container could have been downloaded on the fly to a temporary file, or into memory.
      • The resource could have been created on the fly; e.g. by a clever class loader that decrypts or uncompresses something else.
    2. You are assuming that "Employees.xlsx" will have the same resource path as file system path. This is pretty much guaranteed to not be the case. (It can only be the case if you put the root of the filesystem on the classpath ....)

    I am not sure why you are trying to do this at all. Per @fabian's answer, POI allows you to open a spreadsheet from a InputStream. You should not need a FileInputStream here.

    But in situations where you do need a FileInputStream for a resource on the resource path, the portable solution is to copy the resource to a temporary file, and then open a FileInputStream on the temporary file.