0

I am trying to add an very useful extension method to Java’s InputStream class, since we know stream parsing requires several lines of boiler plate code and In my application we need to process stream multiple times.

So far my extension function works, But it is begin really very useful for some of the drawback we are facing with kotlin core language feature.

My extension Function to Java Stream accepting single argument method definition.

fun InputStream.forEachLine(consumer: (line: String)->Unit){
    val reader = BufferedReader(InputStreamReader(this, Charset.defaultCharset()))
    var line: String? = null
    line = reader.readLine()
    while (line != null) {
        consumer(line)
        line = reader.readLine()
    }
}

//My Test is here
@Test
fun testExtnInputStreamForEachLine() {
    val stream = FileInputStream(File("c:\temp\sometextfile.txt"))
        stream.forEachLine {
            println(it)

            if(it.equals("some text")
            // I want to break the whole forEachLine block 

        }
}

In the above example I have the following approaches:

  • return@forEachLine (this is working good for skipping the same block processing, similar to continue)
  • created a run block with label and tried with return on it. (gives compile time error)
  • break@withLabel (compile time error)
  • changed method returning boolean instead of Unit and tried returning false (compile time error)
Lovis
  • 9,513
  • 5
  • 31
  • 47
Manish Bansal
  • 185
  • 11
  • what would you like to do? To end `print`-ing the lines in case you find a line equal to "some text"? – user2340612 May 31 '18 at 09:41
  • 1
    Kotlin already defines `forEachLine` extension for `Reader` types. What version of Kotlin are you using? https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/java.io.-reader/for-each-line.html – Muli Yulzary May 31 '18 at 10:37

2 Answers2

1

Change to: consumer: (line: String) -> Boolean like this:

fun InputStream.forEachLine(consumer: (line: String) -> Boolean){
    val reader = BufferedReader(InputStreamReader(this, Charset.defaultCharset()))
    var line: String? = null
    line = reader.readLine()
    while (line != null) {
        if (consumer(line))
            break
        line = reader.readLine()
    }
}

//My Test is here
@Test
fun testExtnInputStreamForEachLine() {
    val stream = FileInputStream(File("c:\temp\sometextfile.txt"))
    stream.forEachLine {
        println(it)
        if(it.equals("some text")) true else false
    }
}
0

Returning boolean does not work nice, as I have mentioned above in the question. making my extension function to Inline solved my issue.

Instead of

fun InputStream.forEachLine(consumer: (line: String)->Unit){

it should be

inline fun InputStream.forEachLine(consumer: (line: String)->Unit){

Notice the Inline keyword above and with this, it now allow us to exist from the loop by support return and return to a label.

Manish Bansal
  • 185
  • 11