Alternative to println()? - kotlin

If we don't have the println() function, is there any alternative or a way to write your print function?

If you right-click on println in IntelliJ, you can Go to... -> Implementation(s) and see how Kotlin does it "under the hood". It's a bit verbose but not that complicated. Ultimately it's using a BufferedWriter to write to the Standard Output stream.
You can replicate this yourself with something like:
import java.io.BufferedWriter
import java.io.OutputStreamWriter
fun main() {
val writer = BufferedWriter(OutputStreamWriter(System.`out`))
writer.write("No println here")
writer.newline()
writer.flush()
}

Related

Junit - how to get test result as string?

I am trying to test the code and get a result as String to send it to API later.
class FirstClass{
fun main(){
print("Hello world!")
}
}
Test:
ort org.junit.jupiter.api.AfterEach
import org.junit.jupiter.api.BeforeEach
import org.junit.jupiter.api.Test
import java.io.ByteArrayOutputStream
import java.io.PrintStream
import kotlin.test.assertEquals
internal class FirstClassTest {
private val outContent = ByteArrayOutputStream()
private val errContent = ByteArrayOutputStream()
private val originalOut = System.out
private val originalErr = System.err
#BeforeEach
fun setUp() {
System.setOut(PrintStream(outContent))
System.setErr(PrintStream(errContent))
}
#AfterEach
fun tearDown() {
System.setOut(originalOut)
System.setErr(originalErr)
}
#Test
fun main() {
val SUT = FirstClass()
SUT.main()
val testResult = assertEquals("Hello world!", outContent.toString())
print("Test result: $testResult")
val api = Api()
val apiResult = api.sendResult(testResult.toString())
print("Api result: $apiResult")
}
}
The test is passing, however, I do not see printed messages. How to get a test result as String?
There are several issues here.  The main one is:
The redirection affects your test method too.
Because you've redirected System.out, the print() in your test method goes to outContent, along with the output from FirstClass.main() that you want to test, instead of to the screen or wherever you want it.
I can see two fixes for this.
The quick one is for your test method to output to originalOut:
originalOut.print("Test result: $testResult")
Your test method is in the class which does the redirection, so there's no problem with it knowing about the redirection, and it already has access to originalOut.
However, if you can, I think a better solution is to refactor FirstClass so that it doesn't hard-code the stream it writes to.  For example, the stream could be passed as a parameter; or it could return the string directly (and the caller, in a thin non-tested wrapper, could write it to System.out).
That would be more work, but would make your code more flexible as well as easier to test.
Other issues include:
You're using print() instead of println().
Many streams are line-buffered, writing their output only after a newline, and so you might not see any results if there isn't one.  (And even if you do, all the results would be jammed on a single line!)
You assign the result of assertEquals().
assertEquals() doesn't have a useful return value.  (It return Unit.)  So your code will simply show:
Test result: kotlin.Unit
Instead, like all the assert functions, it throws an exception if the assertion fails.  So there's no point in storing or processing the return value; simply calling the assertion is enough.
— This means that there's usually no need to call print()/println() from your test method anyway!  If there's a failure, it'll be obvious: running from the command line will stop with an exception message and stack trace; IntelliJ shows a big red mark next to that test; Maven and Gradle will stop the build (after all tests have run), showing the number of failures.  So if everything continues smoothly, you know the tests have passed.
Api is not defined.
The code you posted above won't compile, because it doesn't include a definition or import for Api.  (Those last lines can be removed, though, without affecting the question.)
main() is a confusing name for a test.
The unit testing framework will find and run all test methods annotated with #Test.  A test class will often contain many different test methods, and it's usual to name them after the aspect they're testing.  (That makes any failures clearer.)  Calling it main() not only fails to describe what's being tested, but also suggests that the method will be run from outside the testing framework, which would probably not behave properly.

What is the equivalent of Files.lines() in Kotlin?

Is there an equivalent of Java Files.lines() in Kotlin ?
The Java code I would like to convert is similiar to
Stream<String> lines =
Files.list(Paths.get(dir_in))
.flatMap((Files::lines));
// do something with my stream
lines.close();
I'm interested in the ability to release all the files system resources by closing the Stream.
Thanks in advance.
I would use File#bufferedReader
It returns a BufferedReader, which you can (a) close when you want and (b) get the stream of lines with BufferedReader#lines.
Here's some example code.
val buffer: BufferedReader = File("hi.txt").bufferedReader()
val stream: Stream<String> = buffer.lines()
stream.forEach { println(it) }
buffer.close()
You should use the File#useLines function whenever possible, as it auto-closes the steam.

import kotlinx is impossible in IntelliJ IDEA

I`m testing coroutine example code on IntelliJ IDEA. But I cannot import library which needs for coroutine.
I created project as Kotlin - "JVM | IDEA". I tried simple print hello world code and succeesfully done. But coroutine example don`t even execute.
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
fun main()
{
runBlocking {
var counter = 0
val lock = Mutex()
val coroutines = List(3) {
launch {
repeat(1_000) {
lock.withLock {
counter++
}
}
}
}
coroutines.forEach { it.join() }
println("Final counter: $counter")
}
}
This Code runs on https://play.kotlinlang.org. But in IDEA, they cannot understand it, showing 'Unresolved reference'.
I`ve searched but no answer found. How can I run this on IDEA project?
it would be a good idea to switch to a Gradle-based build, which will automatically be imported by IntelliJ IDEA.
you can set IntelliJ to automatically stay in sync with your Gradle files, or you can opt to "sync" IntelliJ to Gradle's structure on demand.
you have two syntax options with Gradle: Groovy and Kotlin. make sure if you are new to Gradle that you use a consistent syntax, otherwise it can be hard to follow the guides. obviously if you are working in Kotlin, it's a great idea to use Kotlin in your build files, too.

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")