Мне нужно прочитать текстовый файл с помощью readLines()
, и я уже нашел этот вопрос, но код в ответах всегда использует некоторые варианты javaClass
; похоже, он работает только внутри класса, в то время как я использую простой файл Kotlin без объявленных классов. С точки зрения синтаксиса это правильно, но выглядит действительно некрасиво и всегда возвращает null
, так что это должно быть неправильно:
val lines = object {}.javaClass.getResource("file.txt")?.toURI()?.toPath()?.readLines()
Конечно, я мог бы просто указать необработанный путь вот так, но мне интересно, есть ли способ лучше:
val lines = File("src/main/resources/file.txt").readLines()
3 ответа
Спасибо этому ответу за предоставление правильного способа чтения файла. В настоящее время чтение файлов из ресурсов без использования javaClass
или подобных конструкций кажется невозможным.
// use this if you're inside a class
val lines = this::class.java.getResourceAsStream("file.txt")?.bufferedReader()?.readLines()
// use this otherwise
val lines = object {}.javaClass.getResourceAsStream("file.txt")?.bufferedReader()?.readLines()
Согласно другим подобным вопросам, которые я обнаружил, второй способ также может работать в лямбде, но я его не тестировал. Обратите внимание на необходимость оператора ?.
и синтаксиса lines?.let {}
, необходимых с этого момента, поскольку getResourceAsStream()
возвращает null
, если ресурс с заданным именем не найден.
object {}
- хороший обходной путь, когда вы находитесь вне класса. Кстати, если вам интересно, следует ли вам использовать javaclass
или class.java
, см. stackoverflow.com/questions/46674787/…
Kotlin не имеет собственных средств получения ресурса, поэтому вам придется использовать метод Java Class.getResource
. Вы не должны предполагать, что ресурс является файлом (т.е. не используйте toPath
), поскольку это вполне может быть запись в jar, а не файл в файловой системе. Чтобы прочитать ресурс, проще получить ресурс как InputStream
, а затем прочитать из него строки:
val lines = this::class.java.getResourceAsStream("file.txt").bufferedReader().readLines()
object {}.javaClass
, что необходимо в моем случае.
Я не уверен, пытается ли мой ответ ответить на ваш точный вопрос, но, возможно, вы могли бы сделать что-то вроде этого:
Я предполагаю, что в конечном варианте использования имена файлов будут динамическими - не объявлены статически. В этом случае, если у вас есть доступ к папке или вы знаете путь к ней, вы можете сделать что-то вроде этого:
// Create an extension function on the String class to retrieve a list of
// files available within a folder. Though I have not added a check here
// to validate this, a condition can be added to assert if the extension
// called is executed on a folder or not
fun String.getFilesInFolder(): Array<out File>? = with(File(this)) { return listFiles() }
// Call the extension function on the String folder path wherever required
fun retrieveFiles(): Array<out File>? = [PATH TO FOLDER].getFilesInFolder()
Если у вас есть ссылка на объект List<out File>
, вы можете сделать что-то вроде этого:
// Create an extension function to read
fun File.retrieveContent() = readLines()
// You can can further expand this use case to conditionally return
// readLines() or entire file data using a buffered reader or convert file
// content to a Data class through GSON/whatever.
// You can use Generic Constraints
// Refer this article for possibilities
// https://kotlinlang.org/docs/generics.html#generic-constraints
// Then simply call this extension function after retrieving files in the folder.
listOfFiles?.forEach { singleFile -> println(singleFile.retrieveContent()) }
Похожие вопросы
Связанные вопросы
Новые вопросы
file
Блок произвольной информации или ресурс для хранения информации, доступный по строковому имени или пути. Файлы доступны для компьютерных программ и обычно основаны на постоянном хранилище.
toURI()?.toPath()
, которого не было в ответах, на которые вы ссылаетесь.file.txt
не существует нигде в файловой системе, и к нему нельзя получить доступ как к файлу. И я думаю, что подходobject {}
вполне подходит. В качестве альтернативы вы можете использовать любой класс из вашего модуля.