Kotlin reading from file exception [duplicate] - kotlin

This question already has answers here:
Can't read file in kotlin even though the file is in the same path as main.kt
(2 answers)
Closed 4 months ago.
private object Bot {
val token = File("token.txt").reader().readLines()
fun setup() {
}
}
fun main(args: Array<String>) {
print(Bot.token)
}
Even though the token.txt file is in the same directory as the Bot.kt file it throws a java.io.FileNotFoundException.

If you only specify "token.txt" it will refer to the root directory of the project not to the directory of the class that is calling. Here you can see
how you can specify paths (example is in java but that is the library that kotlin JVM is using)
So in your case if you want to keep file next to the class it will probably look something like
File("src/main/kotlin/token.txt")
Or whatever your file structure looks like
Edit to explain your comment File("token.txt").absolutePath will return the path as the string and calling reader().readLines() on that will just read that returned string(path) not the contents

Related

How to get declaring KtFile/KtClass using KtCallExpression?

I'm using kotlin compiler to analyze kotlin source file and I need to get where the method is defined using KtCallExpression.
KtCallExpression in question is retrieved from method call.
For better explanation, here's example, if there's source file named Main.kt with contents:
fun main() {
f1()
Test.f2()
}
fun f1() {
}
class Test {
companion object {
fun f2() {
}
}
}
when analyzing function main, it will produce 2 KtCallExpression, one for f1() and other for f2()
However I'm not sure how to get file Main.kt from KtCallExpression for f1(), or class Test from KtCallExpression for f2()
I tried to look for its documentations, however Kotlin compiler doesn't contain enough docs. I've also tried bunch of auto completion suggested by Intellij Idea but none of those doesn't seem to lead me to original declaration.

Kotlin compile error "unresolved reference" only when compiling from command line

I have the Kotlin code:
import com.google.gson.Gson
import java.io.File
class System {
/*
Save current game state to file
*/
internal fun saveGameState(game: Game) {
val gameState = game.getGameState()
val gson = Gson()
val jsonString = gson.toJson(gameState)
val pathname = FILENAME_SAVED_GAME
File(pathname).writeText(jsonString)
}
private fun loadGameState(): Game {
val jsonString = File(FILENAME_SAVED_GAME).readText(Charsets.UTF_8)
val gson = Gson()
val gameState: GameState = gson.fromJson(jsonString, GameState::class.java)
File(FILENAME_SAVED_GAME).delete()
return Game(gameState)
}
...
}
When I run it from within IntelliJIDEA, it compiles and runs fine, including using this class to save state and restore state.
When I compile it from the command line, I use this command:
kotlinc *.kt -include-runtime -d GizmosK.jar
and I this error message:
System.kt:1:12: error: unresolved reference: google
import com.google.gson.Gson
^
System.kt:11:20: error: unresolved reference: Gson
val gson = Gson()
^
System.kt:19:20: error: unresolved reference: Gson
val gson = Gson()
^
I've successfully used this command many times before, but possibly not since adding this System class, which is the only one that imports anything from outside my project.
I've searched, and found this question which appears very similar to my problem, but I have a few concerns.
First, I don't know if this solution applies to my situation since my code is pure Kotlin and not Android.
Second, I don't know how to generalize their solution and make it apply to my situation. Like, I know I probably have to replace something with google.gson or com.google.gson or com.google.gson.Gson in there somewhere, but I don't know where, since there are three things there that look like package names. Do I need all three? I also don't know if expressions like package_name are literal strings I should enter verbatim or if I should replace those words with the actual package name.
Third, I've never had to specify flovar/flavor nor resource_package before in a command line, and I don't want to introduce new variables, if at all possible.
BTW, I'm compiling from the command line to generate a .jar file to distribute so anyone can run it from the command line without sharing my code or requiring they install IntelliJ IDEA.

Service Loader Can't Find Provider

I am having trouble getting the service loader to find my providers. My set up is as follows:
I have 4 modules:
EntryPoint
Library
Version1
Version2
In Library, I have an interface defined:
interface Parent{
fun doSomething()
fun getName()
}
In Version1 and Version2, I override that interface with a class called Impl. I also place
META-INF/services/parent.package.path.Parent
in the resources folder, with
child.package.path.Impl
as its contents.
In EntryPoint I have a main function with the following code:
fun main(args<String>){
val impls = ServiceLoader.load(Parent::class.java)
val implToUse = impls.find { i -> i.getName() == args[0]}
implToUse!!.doSomething()
}
The idea is to be able to load the implementation classes from the entry point dynamically to cut down on build times. everything compiles, but when I run the main function, I get a null pointer exception because none of the providers were loaded.
Not sure what else is required to get the ServiceLoader to "see" the providers. A few notes:
in the build folder generated during compilation, the META-INF resource does (in fact) appear in resouces.
in the build folder generated during compilation, there is no jar being created. Not sure if that is what is causing the issue, or if it is, how to fix

Kotlin class won't let me extend abstract class from different file

I am working on an object-oriented project, and I want to improve my understanding of the OOP part of Kotlin. I have the following abstract class:
package Objecttest
abstract class Abstractclasstest {
abstract fun testString(s: String): String
}
Now I want to extend it in a new class in a different file like this:
package Objecttest
public class Newclasstest : Abstractclasstest() {
override fun testString(s: String): String {
return s
}
}
but when I try compiling Newclasstest.kt, I am met with the following error message: "error: unresolved reference: Abstractclasstest".
Folder structure:
Objecttest/
├── Abstractclasstest.kt
├── Newclasstest.kt
Why is this and how can I work around it? The most important bit is why, because I want to avoid the same mistake in the future.
It seems to me that you need to compile Abstractclasstest.kt first using kotlinc Abstractclasstest.kt and only then compile Newclasstest.kt as follows: kotlinc -cp . Newclasstest.kt. This will search for class files in the same path as Newclasstest.kt on which it should already find the one corresponding to Abstractclasstest.kt. Or you can just compile the 2 files at the same time using kotlinc *.kt.

Run single Kotlin file

I have two Kotlin files in the same folder:
Both files have a trivial main method.
I can right click on helloworld.kt file and select "Run..." from the menu.
There's no such option for the circle.kt file though.
This is my run/debug configuration for helloworld.kt:
I tried to create an equivalent configuration for circle.kt, but it complains that the class com.example.kotlin.learning.CircleKt has no main method:
There's actually no class in that file. But there isn't one in HelloWorld.kt as well, and that works.
Here's the code for helloworld.kt:
package com.example.kotlin.learing
fun main (argomenti: Array<String>) {
println ("SUCA!")
println (saluta ( "mario"))
val vettore : Array<String> = arrayOf("pippo", "pluto", "paperino")
println(vettore [0])
}
fun saluta (chi : String) = ( chi + " antani" )
here's circle.kt:
package com.example.kotlin.learing
fun main() = println("pippuz!")
I realize I am missing something deep here. What is that?
Thanks
If I'm not mistaken, main method without parameters is supported from Kotlin version 1.3-RC. Which version of Kotlin are you using?
If you are using an older version of Kotlin, you should pass an array of Strings as the argument of the main method.