Мне нужно прочитать текстовый файл с помощью readLines(), и я уже нашел этот вопрос, но код в ответах всегда использует некоторые варианты javaClass; похоже, он работает только внутри класса, в то время как я использую простой файл Kotlin без объявленных классов. С точки зрения синтаксиса это правильно, но выглядит действительно некрасиво и всегда возвращает null, так что это должно быть неправильно:

val lines = object {}.javaClass.getResource("file.txt")?.toURI()?.toPath()?.readLines()

Конечно, я мог бы просто указать необработанный путь вот так, но мне интересно, есть ли способ лучше:

val lines = File("src/main/resources/file.txt").readLines()
1
rdxdkr 15 Дек 2021 в 13:17
Я предполагаю, что вы получите null из-за toURI()?.toPath(), которого не было в ответах, на которые вы ссылаетесь. file.txt не существует нигде в файловой системе, и к нему нельзя получить доступ как к файлу. И я думаю, что подход object {} вполне подходит. В качестве альтернативы вы можете использовать любой класс из вашего модуля.
 – 
broot
15 Дек 2021 в 13:25

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, если ресурс с заданным именем не найден.

1
rdxdkr 15 Дек 2021 в 15:56
1
Действительно, использование object {} - хороший обходной путь, когда вы находитесь вне класса. Кстати, если вам интересно, следует ли вам использовать javaclass или class.java, см. stackoverflow.com/questions/46674787/…
 – 
k314159
15 Дек 2021 в 17:26

Kotlin не имеет собственных средств получения ресурса, поэтому вам придется использовать метод Java Class.getResource. Вы не должны предполагать, что ресурс является файлом (т.е. не используйте toPath), поскольку это вполне может быть запись в jar, а не файл в файловой системе. Чтобы прочитать ресурс, проще получить ресурс как InputStream, а затем прочитать из него строки:

val lines = this::class.java.getResourceAsStream("file.txt").bufferedReader().readLines()
2
k314159 15 Дек 2021 в 14:59
Спасибо, сработало. Я добавляю свой собственный ответ с версией, в которой используется object {}.javaClass, что необходимо в моем случае.
 – 
rdxdkr
15 Дек 2021 в 15:37

Я не уверен, пытается ли мой ответ ответить на ваш точный вопрос, но, возможно, вы могли бы сделать что-то вроде этого:

Я предполагаю, что в конечном варианте использования имена файлов будут динамическими - не объявлены статически. В этом случае, если у вас есть доступ к папке или вы знаете путь к ней, вы можете сделать что-то вроде этого:


// 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()) }
1
Clinkz 15 Дек 2021 в 15:40
Я ценю ответ, но это немного излишне для того, что мне нужно сделать прямо сейчас. В любом случае, спасибо.
 – 
rdxdkr
15 Дек 2021 в 16:00