diff --git a/stdlib/ktSrc/JavaIo.kt b/stdlib/ktSrc/JavaIo.kt index 03efc943a1a..8333eb37ca4 100644 --- a/stdlib/ktSrc/JavaIo.kt +++ b/stdlib/ktSrc/JavaIo.kt @@ -111,28 +111,31 @@ inline fun InputStream.reader(charsetDecoder: CharsetDecoder) = InputStreamReade inline val InputStream.buffered : BufferedInputStream get() = if(this is BufferedInputStream) this else BufferedInputStream(this) -// inline val Reader.buffered : BufferedReader +// inline val Reader.buffered : BufferedReader // get() = if(this is BufferedReader) this else BufferedReader(this) -inline fun Reader.buffered() = BufferedReader(this) +inline fun Reader.buffered(): BufferedReader = if(this is BufferedReader) this else BufferedReader(this) inline fun Reader.buffered(bufferSize: Int) = BufferedReader(this, bufferSize) +inline fun Reader.useLines(block: (Iterator) -> T): T = this.buffered().use{block(it.lineIterator())} +/** + * Returns an iterator over each line. + * Note the caller must close the underlying BufferedReader + * when the iteration is finished; as the user may not complete the iteration loop (e.g. using a method like find() or any() on the iterator + * may terminate the iteration early. + *
+ * We suggest you try the method useLines() instead which closes the stream when the processing is complete. + */ inline fun BufferedReader.lineIterator() : Iterator = LineIterator(this) protected class LineIterator(val reader: BufferedReader) : Iterator { private var nextLine: String? = null - private var closed = false override val hasNext: Boolean get() { nextLine = reader.readLine() - val answer = nextLine != null - if (! answer && !closed) { - closed = true - reader.close() - } - return answer + return nextLine != null } override fun next(): String = nextLine.sure() diff --git a/testlib/test/IoTest.kt b/testlib/test/IoTest.kt index 380d31a0b51..ac80a455135 100644 --- a/testlib/test/IoTest.kt +++ b/testlib/test/IoTest.kt @@ -10,18 +10,33 @@ import java.util.* class IoTest() : TestSupport() { val file = File("test/HelloWorld.txt") + fun testLineIteratorWithManualClose() { + val reader = FileReader(file).buffered() + try { + val list = reader.lineIterator().toArrayList() + assertEquals(arrayList("Hello", "World"), list) + } finally { + reader.close() + } + } + + fun testLineIterator() { - val list = FileReader(file).buffered().lineIterator().toArrayList() + /* + // TODO compiler error + // both these expressions causes java.lang.NoClassDefFoundError: collections/namespace + val list = FileReader(file).useLines{it.toArrayList()} + val list = FileReader(file).useLines>{it.toArrayList()} + assertEquals(arrayList("Hello", "World"), list) + */ } fun testUse() { - val list = ArrayList() - - val reader = FileReader(file).buffered() - reader.close() - /** + val list = ArrayList() + val reader = FileReader(file).buffered() + TODO compiler error? reader.use{ val line = it.readLine()