Write text and Print in Kotlin - kotlin

I have the following code:
package com.zetcode
import java.io.File
fun main() {
val fileName = "P3.txt"
val content = File(P3.txt).readText()
println(content)
}
My goal is to write a code in kotlin that reads the text file (P3.txt) and prints its content. I know there is something wrong because I keep receiving "unresolved reference.

File takes a string as input, you should change the line:
val content = File(P3.txt).readText()
to
val content = File("P3.txt").readText()
The difference is that without the quotes, kotlin thinks P3 is a reference that is not declared anywhere and you get the error you've mentioned.

Related

How should I format and parse a DateTimeFormatter object?

I am trying to parse a date in parseServerTimeOffsetDateTime(), but I keep getting errors. Can't seem to make it work.
Here is what I have done so far:
For some reason the function keeps returning a Unit data type or TemporalAccessor if I try to parse the function with default parse function.
I tried converting it into a String or DataTimeFormatter and similar data types but in those cases it shows errors in try/catch block like a type missmatch and it won't compile.
I checked in documentation but am still unclear what TemporalAccessor is.
I thought of writing my own parser TimeParser, but I am not sure how I should implement it. Since the format of the date is 2022-05-24T07:52:03Z I thought of putting 'T' and 'Z' as a character where it should be parsed.
private val serverTimeFormatterOffsetDateTimeFormatter =
DateTimeFormatter.ISO_ZONED_DATE_TIME
private val fallbackServerTimeFormatterOffsetDateTime =
DateTimeFormatter.ISO_ZONED_DATE_TIME
fun OffsetDateTime.toServerDateFormatOffsetDateTime() = DateTimeFormatter.ofPattern("yyyy-MM-dd")
fun OffsetDateTime.toServerTimeFormatOffsetDateTime() =
serverTimeFormatterOffsetDateTimeFormatter.format(this)
fun String.parseServerTimeOffsetDateTime() = try {
serverTimeFormatterOffsetDateTimeFormatter.TimeParser(this)
} catch (pe: ParseException) {
fallbackServerTimeFormatterOffsetDateTime.TimeParser(this)
}
fun DateTimeFormatter.TimeParser(time: String) {
// Haven't done anything yet here
val delimeter = "T"
val delimeter2 = "Z"
// code for parsing
}
How should I format and parse a DateTimeFormatter object?

File I/O in Kotlin with (potentially) unknown encoding

This is my first attempt to learn and use Kotlin. I have a simple task: read a file line by line, preprocess each line and put a specific portion into a map. Each line is tab-separated.
When trying to preprocess, things start going horribly wrong. I tried to debug, and instead of the normal characters, this is what I can see:
In between every two adjacent readable characters, there is the strange-looking block with horizontal lines.
Here is the code I wrote:
fun mapUserToId(path: String): MutableMap<String, Int> {
val user2id = mutableMapOf<String, Int>()
val bufferedReader = File(path).bufferedReader()
bufferedReader.useLines { lines ->
lines.drop(1).forEach { // dropping the first line with column headers
val components: List<String> = it.trim().split("\t") // split by tab delimiter
val user: String = components[2]
println(user.length) // length is nearly double due to the strange block-like characters
val id: String = components[3]
user2id[user] = id.toInt() // fails due to number format exception, because of those block-like characters
}
}
return user2id
}
This looks like a charset issue, but I can't figure out what the charset could be, and how to specify that charset in the above code. Opening the file in vim looks perfectly normal (as in, one would suspect that this file has UTF-8 encoding).
This is, indeed, an encoding issue. The problem is resolved by specifying the encoding while creating the buffered reader as follows:
val bufferedReader: BufferedReader = File(path).bufferedReader(Charsets.UTF_16)

Why won't Kotlin print the string I select from a .txt file unless it's the last line?

I'm using to open a text file, randomly select a line, and format a string that includes the randomly selected line. The string is then printed to the console, but for some reason it won't work unless the last line of the file gets randomly selected.
Text file:
Neversummer
Abelhaven
Phandoril
Tampa
Sanortih
Trell
Zan'tro
Hermi Hermi
Curlthistle Forest
Code:
import java.io.File
fun main() {
var string = File("data/towns.txt")
.readText()
.split("\n")
.shuffled()
.first()
println("$string has printed")
}
Output when last line is selected:
Curlthistle Forest has printed
Output when any other line is selected:
has printed
As suggested by dyukha in the comment section it is indeed a platform specific issue. I prefer the solution (s)he provided using readLines() since you can condense two function calls into one.
However, should you ever need to check for the line delimiter in a platform independent manner you should use the built-in System.lineSeparator() property (Since Java 7).
import java.io.File
fun main() {
var string = File("data/towns.txt")
.readText()
.split(System.lineSeparator())
.shuffled()
.first()
println("$string has printed")
}
...
Still, I do recommend that you use readLines() since it packages the functionality of both .readText() and .split(System.lineSeparator()).

Kotlin dynamically compile a class from source code at runtime

Is it possible to compile and instantiate Kotlin class at runtime? I'm talking about something like that but using Kotlin API: How do I programmatically compile and instantiate a Java class?
As example:
I'm getting full class definition as String:
val example = "package example\n" +
"\n" +
"fun main(args: Array<String>) {\n" +
" println(\"Hello World\")\n" +
"}\n"
And then inserting it into some class.kt and running it so I'm getting "Hello World" printed in console at runtime.
You might want to look at Kotlin Scripting, see https://github.com/andrewoma/kotlin-script
Alternatively, you'll need to write your own eval(kotlin-code-string-here) method which will dump the text inside blah.kt file for example, compile it using an external Kotlin compiler into blah.class then dynamically load those classes into the runtime using the Java Classloader doing something like this:
MainClass.class.classLoader.loadClass("com.mypackage.MyClass")
This might be very slow and unreliable.
Another no so great option is to make use of Rhino and run JavaScript inside your Kotlin code. So once again, you'll have an eval(kotlin-code-string-here) method which will dump the content to a blah.kt file, then you would use a Kotlin2JS compiler to compile it to JavaScript and directly execute the JavaScript inside Kotlin using Rhino which is not great either.
Another option is to make use of Kotlin Scripting or an external Kotlin compiler (in both cases, the Kotlin compiler will have to start up) and doing something like this will also allow you to execute dynamically, albeit, only on Unix systems.
Runtime.getRuntime().exec(""" "kotlin code here" > blah.kts | sh""")
I'm not aware of a clean solution for this, Kotlin was not designed to be run like like PHP / JavaScript / Python which just interprets text dynamically, it has to compile to bytecode first before it can do anything on the JVM; so in each scenario, you will need to compile that code first in one way or another, whether to bytecode or to javascript and in both cases load it into you application using the Java Classloader or Rhino.
Please check this solution for dependencies, jar resources, etc. Code below isn't enough for successful execution.
However, to compile dynamic class you can do the following:
val classLoader = Thread.currentThread().contextClassLoader
val engineManager = ScriptEngineManager(classLoader)
setIdeaIoUseFallback() // hack to have ability to do this from IntelliJ Idea context
val ktsEngine: ScriptEngine = engineManager.getEngineByExtension("kts")
ktsEngine.eval("object MyClass { val number = 123 } ")
println(ktsEngine.eval("MyClass.number"))
Please note: there is code injection possible here. Please be careful and use dedicated process or dedicated ClassLoader for this.
KotlinScript can be used to compile Kotlin source code (e.g. to generate a jar file that can then be loaded).
Here's a Java project which demonstrates this (code would be cleaner in Kotlin):
https://github.com/alexoooo/sample-kotlin-compile/blob/main/src/main/java/io/github/alexoooo/sample/compile/KotlinCompilerFacade.java
Note that the code you provide would be generated as a nested class (inside the script).
Here is a Kotlin version:
#KotlinScript
object KotlinDynamicCompiler {
//-----------------------------------------------------------------------------------------------------------------
const val scriptClassName = "__"
const val classNamePrefix = "${scriptClassName}$"
private val baseClassType: KotlinType = KotlinType(KotlinDynamicCompiler::class.java.kotlin)
private val contextClass: KClass<*> = ScriptCompilationConfiguration::class.java.kotlin
//-----------------------------------------------------------------------------------------------------------------
fun compile(
kotlinCode: String, outputJarFile: Path, classpathLocations: List<Path>, classLoader: ClassLoader
): String? {
Files.createDirectories(outputJarFile.parent)
val scriptCompilationConfiguration = createCompilationConfigurationFromTemplate(
baseClassType, defaultJvmScriptingHostConfiguration, contextClass
) {
jvm {
val classloaderClasspath: List<File> = classpathFromClassloader(classLoader, false)!!
val classpathFiles = classloaderClasspath + classpathLocations.map { it.toFile() }
updateClasspath(classpathFiles)
}
hostConfiguration(ScriptingHostConfiguration (defaultJvmScriptingHostConfiguration) {
jvm {
compilationCache(
CompiledScriptJarsCache { _, _ ->
outputJarFile.toFile()
}
)
}
})
}
val scriptCompilerProxy = ScriptJvmCompilerIsolated(defaultJvmScriptingHostConfiguration)
val result = scriptCompilerProxy.compile(
kotlinCode.toScriptSource(KotlinCode.scriptClassName), scriptCompilationConfiguration)
val errors = result.reports.filter { it.severity == ScriptDiagnostic.Severity.ERROR }
return when {
errors.isEmpty() -> null
else -> errors.joinToString(" | ")
}
}
}

Kotlin - println using string template to stderr

How do I send output of println() to System.err. I want to use string template.
val i = 3
println("my number is $i")
println() sends message to stdout and it looks like there is no option to send to stderr.
Kotlin unfortunately does not provide ubiquitous way to write to stderr.
If you target JVM with Kotlin you can use the same API as in Java.
System.err.println("Hello standard error!")
In case of Kotlin Native you can use a function that opens the stderr and writes to it manually with the use of platform.posix package.
val STDERR = platform.posix.fdopen(2, "w")
fun printErr(message: String) {
platform.posix.fprintf(STDERR, "%s\n", message)
platform.posix.fflush(STDERR)
}
printErr("Hello standard error!")
Note: Using formatting function printf may have security implications. Format string vulnerability can crash your application and you may want to consider using _s "secure" variant of printf function.
In multi-platform projects one can use mechanism of expect and actual function to provide single interface to write to STDERR on all platforms.
// Common
expect fun eprintln(string: String): void
// JVM
actual fun eprintln(string: String) = System.err.println(string)
https://kotlinlang.org/docs/reference/platform-specific-declarations.html
You can just do it like you would in Java:
System.err.println("hello stderr")
The standard stdout output just gets the special shorter version via some helper methods in Kotlin because it's the most often used output. You could use that with the full System.out.println form too.
why not create a global function
fun printErr(errorMsg:String){
System.err.println(errorMsg)
}
then call it from anyware
printErr("custom error with ${your.custom.error}")
If you want to print error as like Java in Kotlin then check the below code:
System.err.println("Printing Error")
It will print it in red color.
But if you use just only println() then it will work like:
System.out.println("Printing Hello")