# Kotlin Coroutine Confidence: asynchronous read file

**URL:** <https://forum.devtalk.com/t/kotlin-coroutine-confidence-asynchronous-read-file/196265>\
**Category:** PragProg Customers\
**Tags:** book-kotlin-coroutine-confidence\
**Created:** [23 April 2025 22:08 UTC](https://forum.devtalk.com/t/kotlin-coroutine-confidence-asynchronous-read-file/196265 "2025-04-23T22:08:31Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![dhmitchell](https://forum.devtalk.com/user_avatar/forum.devtalk.com/dhmitchell/32/7269_2.png) [@dhmitchell](https://forum.devtalk.com/u/dhmitchell)\
**Post date:** [23 April 2025 22:08 UTC](https://forum.devtalk.com/t/kotlin-coroutine-confidence-asynchronous-read-file/196265/1 "2025-04-23T22:08:31Z")

</div>

In “gallery/v14/src/main/kotlin/com/example/gallery/GetImageFromFile.kt”

- won’t the `.use` always call `channel.close()` on exit? if so, why do you need `invokeOnCancellation`? or does cancellation somehow avoid the `finally` in the `use`?
- if I wanted to iterate through the file line by line, I presume I’d call `readline` rather than `read` and otherwise it’s roughly the same?

---

<div class="post-metadata">

**Author:** ![sam-cooper](https://forum.devtalk.com/user_avatar/forum.devtalk.com/sam-cooper/32/7446_2.png) [@sam-cooper](https://forum.devtalk.com/u/sam-cooper)\
**Post date:** [24 April 2025 07:43 UTC](https://forum.devtalk.com/t/kotlin-coroutine-confidence-asynchronous-read-file/196265/2 "2025-04-24T07:43:49Z")

</div>

Yes, since the `use()` block wraps the entire call to `suspendCancellableCoroutine()`, it will always close the `AsynchronousFileChannel` when `suspendCancellableCoroutine()` exits for any reason. The problem is that without that `invokeOnCancellation()` block, `suspendCancellableCoroutine()` will _not_ exit—at least, not until we’ve finished reading the entire file.

What we’re trying to do by adding `invokeOnCancellation()` is to ensure that we can stop the file operation _before_ it finishes. When the coroutine is cancelled, Kotlin executes the `invokeOnCancellation()` block. Calling `channel.close()` inside the block is how we interrupt the ongoing file operation and cause it to end early.

That means there are two different ways the file can be closed:

1. The `read()` operation ends on its own, either because it reached the end of the file or because it ran into an I/O error. The suspension point resumes, and the coroutine exits the `use()` block, closing the channel in the process.
2. The user cancels the coroutine before `read()` is done. This triggers `invokeOnCancellation()`, which in turn calls `channel.close()`. This fires the `read()` operation’s `failed()` callback, allowing the coroutine to resume from its suspended state without waiting for the rest of the data. Again, it exits the `use()` block, but the file channel is already closed, so that’s a no-op.

I’ll see what I can do to make all this clearer in the book! Although it’s not something you’re likely to have to deal with often, I’d like to make sure it’s clear.

As for the second question, that’s a little trickier. The `AsynchronousFileChannel` just deals with raw byte data, and it doesn’t have any methods for working with text or line separators. Unfortunately that means there’s no `readLine()` function. You could write one of your own, but you’d need to include logic to buffer the data in chunks, inspect it for line separators, and so on.

In a real application, it’s likely that the more complete feature set of the `java.io` libraries will outweigh any asynchronous advantage from using `java.nio`. If I needed to read lines from a text file, I’d probably just use a good old fashioned `Reader`, and accept the minor cost of a blocked IO thread. In the book, I’m not intending to advocate for using `AsynchronousFileChannel` all over the place—it’s just meant as a handy example of a simple (ish) operation that we can use to illustrate asynchronous callbacks. Perhaps I’ll add a quick note to that effect in the text, too.

Phew! With any luck, I’ll find a way to say all this in the book using slightly fewer words. Thanks for asking these questions—they all help me to make the explanations in the book clearer.

---

<div class="post-metadata">

**Author:** ![dhmitchell](https://forum.devtalk.com/user_avatar/forum.devtalk.com/dhmitchell/32/7269_2.png) [@dhmitchell](https://forum.devtalk.com/u/dhmitchell)\
**Post date:** [24 April 2025 10:34 UTC](https://forum.devtalk.com/t/kotlin-coroutine-confidence-asynchronous-read-file/196265/3 "2025-04-24T10:34:39Z")

</div>

Yeah, on the readline I realized it needs an intermediate buffered reader. Your answer about use confirmed my expectation. I understood the role of invoke… thank you
