final sclass ByteCountingLineReader implements Closeable { InputStream in; long _byteCount; int bufferedByte = -1; bool ended; *(InputStream *in) {} // in should be buffered! ByteCountingLineReader(File f) { in = bufferedInputStream(f); } S readLine() ctex { new ByteArrayOutputStream baos; if (ended) null; while licensed { int c = read(); if (ended && baos.size() == 0) null; if (ended || c == '\n') break; if (c == '\r') { c = read(); if (c != '\n' && !ended) bufferedByte = c; break; } baos.write(c); } ret fromUtf8(baos.toByteArray()); } int read() ctex { if (bufferedByte >= 0) { int b = bufferedByte; bufferedByte = -1; ret b; } int c = in.read(); if (c < 0) ended = true; else ++_byteCount; ret c; } long byteCount() { ret bufferedByte >= 0 ? _byteCount-1 : _byteCount; } public void close() ctex { if (in != null) try { in.close(); } finally { in = null; } } }