What is the equivalent of Files.lines() in Kotlin? - 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.

Related

Need to filter lines from a sequence but keep it as a single sequence

I need to read a file from disk, filter out some rows based on conditions, then return the result as a single stream/sequence, not a sequence of strings. The file is too large to hold in memory all at once, so it must be treated as a Stream/Sequence throughout processing. This is what I tried.
File(filename).bufferedReader()
// break into lines
.lineSequence()
// filter each line based on condition
.filter{meetsSomeCondition(it)}
// add newline back in
.map{(it+"\n").byteInputStream()}
// reduce back into a single stream with Java's SequenceInputStream
.reduce<InputStream, ByteArrayInputStream> { acc, i -> SequenceInputStream(acc, i) }
This works when testing on a small file, but when using a large file it errors with a StackOverFlow exception. It seems that Java's SequenceInputStream can't handle repeatedly nesting itself like I do with the reduce call.
I see that SequenceInputStream also has a way of accepting an Enumeration argument that takes a List of elements. But that's the problem, as far as I can tell, it doesn't seem to accept a Stream.
Your code does not really do what you think it does. reduce() is a terminal operation, meaning that it consumes all elements in the sequence. After reduce() line the whole file has been read already. Also, it is not SequenceInputStream that does not support such reduce operation. You created a very long chain of objects. SequenceInputStream objects does not really know they were chained like this and they can't do too much about it.
Instead, you need to keep a sequence "alive" and create an InputStream that will read from the source sequence whenever required. I don't think there is an utility like this in the stdlib. It is a very specialized requirement.
The easiest is to create a sequence of bytes and then provide InputStream which reads from it:
File(filename).bufferedReader()
.lineSequence()
.filter{meetsSomeCondition(it)}
.flatMap { "$it\n".toByteArray().asIterable() }
.asInputStream()
fun Sequence<Byte>.asInputStream() = object : InputStream() {
val iter = iterator()
override fun read() = if (iter.hasNext()) iter.next().toUByte().toInt() else -1
}
However, sequence of bytes isn't really the best for performance. We can optimize it by reading line by line, so creating a sequence of strings or byte arrays:
File(filename).bufferedReader()
.lineSequence()
.filter{meetsSomeCondition(it)}
.map { "$it\n".toByteArray() }
.asInputStream()
fun Sequence<ByteArray>.asInputStream() = object : InputStream() {
val iter = iterator()
var curr = iter.next()
var pos = 0
override fun read(): Int {
return when {
pos < curr.size -> curr[pos++].toUByte().toInt()
!iter.hasNext() -> -1
else -> {
curr = iter.next()
pos = 0
read()
}
}
}
}
(Note this implementation of asInputStream() will fail for empty sequence)
Still, there is much room for improvement regarding the performance. We read from sequence line by line, but we still read from InputStream byte by byte. To improve it further we would need to implement more methods of InputStream to read in bigger chunks. If you really care about the performance then I suggest looking into BufferedInputStream implementation and try to re-use some of its codebase.
Also, remember to close the file reader that was created in the first step. It won't close automatically when InputStream will be closed.

How can I use Kotlin to handle asynchronous speech recognition?

The Code A is from the artical https://cloud.google.com/speech-to-text/docs/async-recognize
It write with Java, I don't think the following code is a good code, it make the app interrupt.
while (!response.isDone()) {
System.out.println("Waiting for response...");
Thread.sleep(10000);
}
...
I'm a beginner of Kotlin. How can I use Kotlin to write the better code? maybe using coroutines ?
Code A
public static void asyncRecognizeGcs(String gcsUri) throws Exception {
// Instantiates a client with GOOGLE_APPLICATION_CREDENTIALS
try (SpeechClient speech = SpeechClient.create()) {
// Configure remote file request for FLAC
RecognitionConfig config =
RecognitionConfig.newBuilder()
.setEncoding(AudioEncoding.FLAC)
.setLanguageCode("en-US")
.setSampleRateHertz(16000)
.build();
RecognitionAudio audio = RecognitionAudio.newBuilder().setUri(gcsUri).build();
// Use non-blocking call for getting file transcription
OperationFuture<LongRunningRecognizeResponse, LongRunningRecognizeMetadata> response =
speech.longRunningRecognizeAsync(config, audio);
while (!response.isDone()) {
System.out.println("Waiting for response...");
Thread.sleep(10000);
}
List<SpeechRecognitionResult> results = response.get().getResultsList();
for (SpeechRecognitionResult result : results) {
// There can be several alternative transcripts for a given chunk of speech. Just use the
// first (most likely) one here.
SpeechRecognitionAlternative alternative = result.getAlternativesList().get(0);
System.out.printf("Transcription: %s\n", alternative.getTranscript());
}
}
}
You will have to provide some context to understand what you are trying to achieve, but it looks like coroutine is not really necessary here, as longRunningRecognizeAsync is already non-blocking and returns OperationFuture response object. You just need to decide what to do with that response, or just store Future and check it later. There is nothing implicitly wrong with while (!response.isDone()) {}, that's how Java Futures are supposed to work. Also check OperationFuture, if its normal Java Future, it should implement get() method, that will let you wait for result if necessary, without having to do explicit Thread.sleep().

How to replace blocking code for reading bytes in Kotlin

I have ktor application which expects file from multipart in code like this:
multipart.forEachPart { part ->
when (part) {
is PartData.FileItem -> {
image = part.streamProvider().readAllBytes()
}
else -> // irrelevant
}
}
The Intellij IDEA marks readAllBytes() as inappropriate blocking call since ktor operates on top of coroutines. How to replace this blocking call to the appropriate one?
Given the reputation of Ktor as a non-blocking, suspending IO framework, I was surprised that apparently for FileItem there is nothing else but the blocking InputStream API to retrieve it. Given that, your only option seems to be delegating to the IO dispatcher:
image = withContext(Dispatchers.IO) { part.streamProvider().readBytes() }

Transforming a Spring Webflux Mono to an Either, preferably without blocking?

I'm using Kotlin and Arrow and the WebClient from spring-webflux. What I'd like to do is to transform a Mono instance to an Either.
The Either instance is created by calling Either.right(..) when the response of the WebClient is successful or Either.left(..) when WebClient returns an error.
What I'm looking for is a method in Mono similar to Either.fold(..) where I can map over the successful and erroneous result and return a different type than a Mono. Something like this (pseudo-code which doesn't work):
val either : Either<Throwable, ClientResponse> =
webClient().post().exchange()
.fold({ throwable -> Either.left(throwable) },
{ response -> Either.right(response)})
How should one go about?
There is no fold method on Mono but you can achieve the same using two methods: map and onErrorResume. It would go something like this:
val either : Either<Throwable, ClientResponse> =
webClient().post()
.exchange()
.map { Either.right(it) }
.onErrorResume { Either.left(it).toMono() }
I'm not really familiar with that Arrow library nor the typical use case for it, so I'll use Java snippets to make my point here.
First I'd like first to point that this type seems to be blocking and not lazy (unlike Mono). Translating a Mono to that type means that you'll make your code blocking and that you shouldn't do that, for example, in the middle of a Controller handler or you will block your whole server.
This is more or less the equivalent of this:
Mono<ClientResponse> response = webClient.get().uri("/").exchange();
// blocking; return the response or throws an exception
ClientResponse blockingResponse = response.block();
That being said, I think you should be able to convert a Mono to that type by either calling block() on it and a try/catch block around it, or turning it first into a CompletableFuture first, like:
Mono<ClientResponse> response = webClient.get().uri("/").exchange();
Either<Throwable, ClientResponse> either = response
.toFuture()
.handle((resp, t) -> Either.fold(t, resp))
.get();
There might be better ways to do that (especially with inline functions), but they all should involve blocking on the Mono in the first place.

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