7

I get this error when I start my packaged jar. When I run it from my IDE it does not give the error and run.

java.io.FileNotFoundException: file:\C:\Development\Kotlin\AccountTool\target\AccountTool-1.0-SNAPSHOT-jar-with-dependencies.jar!\accounts.json (The filename, directory name or volume label syntax is incorrect)
    at java.io.FileInputStream.open0(Native Method)
    at java.io.FileInputStream.open(Unknown Source)
    at java.io.FileInputStream.<init>(Unknown Source)
    at java.io.FileInputStream.<init>(Unknown Source)
    at java.io.FileReader.<init>(Unknown Source)
    at com.martacus.accounttool.ToolView$handler.readData(Tool.kt:41)
    at com.martacus.accounttool.ToolView.<init>(Tool.kt:56)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
    at java.lang.reflect.Constructor.newInstance(Unknown Source)
    at java.lang.Class.newInstance(Unknown Source)
    at tornadofx.FXKt.find(FX.kt:238)
    at tornadofx.App.start(App.kt:27)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$159(Unknown Source)
    at com.sun.javafx.application.LauncherImpl$$Lambda$52/31866147.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$172(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$45/2900468.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$170(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$48/4210449.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$171(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$47/24077489.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$145(Unknown Source)
    at com.sun.glass.ui.win.WinApplication$$Lambda$36/1828305.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

Code and file hierarchy in the ide: enter image description here

fun readData(){
    accounts.clear()
    var readFile = ToolView::class.java.classLoader.getResource("accounts.json").file
    println(readFile)
    FileReader(readFile).use{
        var account = gson.fromJson(it, Array<Account>::class.java) ?: return
        for(i in account){
            accounts.add(i)
        }
    }

}

.jar root:

enter image description here

I have no idea what is going wrong and why it is giving me the error. Searching on stackoverflow and google didnt provide me with the right answer. I hope someone here can help me, if you need any more info please say so.

Thanks!

Andrew Thompson
  • 168,117
  • 40
  • 217
  • 433
Martacus
  • 723
  • 6
  • 23

1 Answers1

13

When a resource is packed into a jar, it is not available as a file in filesystem anymore. Therefore you cannot use standard API for working with filesystem as File() or FileReader() to access the contents of the resource.

Instead you should open resource stream with Class.getResourceAsStream or ClassLoader.getResourceAsStream methods and read the content from that stream:

val stream = ToolView::class.java.classLoader.getResourceAsStream("accounts.json")

stream.reader().use {
    println(it.readText())
}
Ilya
  • 21,871
  • 8
  • 73
  • 92
  • 1
    it might also need to be prefixed with `/` as `/accounts.json` because it is not in the same package as ToolView (then again I don't know what package ToolView is in). Or use the system classloader instead. – Jayson Minard Aug 08 '16 at 15:21
  • @JaysonMinard I believe it's required when `getResourceAsStream` is called on a `Class` instance which resolves the name of the resource relative to its package. And here `getResourceAsStream` is invoked on a `ClassLoader`. But anyway, thanks for clarification. – Ilya Aug 08 '16 at 15:29
  • Thanks! It works! But would this also apply for the WriteFile? Since I didnt change that I did get the error when writing. Atlough i dont see a stream.writer() method. – Martacus Aug 08 '16 at 15:51
  • @Martacus resources are for bundling read-only data into a jar, so you couldn't write content to a resource. See this related question: http://stackoverflow.com/q/5052311/869184 – Ilya Aug 08 '16 at 16:04
  • *"But would this also apply for the WriteFile?"* See [How can an app use files inside the JAR for read and write?](http://stackoverflow.com/questions/5052311/how-can-an-app-use-files-inside-the-jar-for-read-and-write/) – Andrew Thompson Aug 09 '16 at 09:00