Чтение ByteArray из файловой системы или Jar в Kotlin - PullRequest
0 голосов
/ 13 сентября 2018

Я часто разрабатываю приложения в IDE, а затем распространяю их с исполняемым JAR.Поэтому я стремлюсь к взаимодействию в отношении библиотечных функций.У меня есть частичное решение, использующее InputStream для надежного чтения данных из файла, расположенного либо в FileSystem, либо в файле Jar, но я хотел бы использовать надежную функцию Kotlin Closable.use() для адаптации к возникающей ошибке илине.

После некоторой борьбы я нашел эту запись , которая объясняет, как сжатие внутри файла Jar делает его доступ отличным от доступа к файловой системе.В частности, хорошая функция расширения Kotlin File.readBytes() не будет работать для файла в банке.Это позор, потому что, глядя на источник readBytes(), есть умное использование функции use() для обработки непредвиденных обстоятельств потока.Он говорит ...

корректно закрывает его независимо от того, сгенерировано исключение или нет.

Вот частичное решение, которое возвращает ByteArray.Эти функции работают одинаково при запуске приложения из среды IDE или из исполняемого файла 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
}

Ответы [ 2 ]

0 голосов
/ 13 сентября 2018

Ты почти у цели. Возможно, вы упустили то, что Kotlin уже определяет метод расширения use () в интерфейсе Closable, который реализует InputStream. Таким образом, ваш второй метод может быть переписан как однострочный:

inline fun <reified T> getResourceByteArray(filename: String)
    = getResourceAsStream<T>(filename).use{ it.readBytes() }
0 голосов
/ 13 сентября 2018

Я включил решение @gidds, чтобы использовать библиотечную функцию Kotlin Closeable.use () как часть операции по загрузке ByteArray из файла ресурсов через InputStream ожидаю, что функция use() позаботится о закрытии InputStream или иным образом будет иметь дело с ошибками, выданными или нет .

В обновленном коде вызывающий Class , предоставленный в виде расширенного типа, дает контекст, для которого каталог resources будет содержать файл.В многопроектной сборке может быть несколько каталогов resources .Это тот случай, когда я работаю с разными проектами, требующими разных входных данных.

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)
= getResourceAsStream<T>(filename).use{ it.readBytes() }

class ReadByteData() {
  init{
    val byteArray= getResourceByteArray<ReadByteData>("fileName")
  }
}
...