I am often developing applications in an IDE and then distributing them with an executable JAR. So I seek interoperability in regards to library functions. I have a partial solution using an InputStream
to robustly read data from a file located in either a FileSystem or a Jar file, but I would like to make use of the robust Kotlin function Closable.use()
to adapt to the error being thrown or not.
After some struggle I found this post that explains how compression inside the Jar file makes its access different than that from a FileSystem. In particular the nice Kotlin extension function File.readBytes()
will not work for a file in a Jar. That is a shame because looking into the source of readBytes()
there is a clever use of the use()
function to handle the stream contingencies. It says...
closes it down correctly whether an exception is thrown or not.
Here is the partial solution which returns a ByteArray. These functions work the same whether running the application from within the IDE or from an executable Jar.
inline fun <reified T> getResourceAsStream(filename:String):InputStream {
//it is calling function's responsibility to close the stream
//force the first character to be a backslash that indicates root
val fnameWithPath= if (filename[0] != '/') "/$filename" else filename
//extract the stream if it exists
return T::class.java.getResourceAsStream(fnameWithPath)
}
inline fun <reified T> getResourceByteArray(filename:String):ByteArray {
//will open a stream, read bytes and then close stream
val stream= getResourceAsStream<T>(filename)
val byteArray = stream.readBytes()
stream.close()
return byteArray
}