Skip to content

Instantly share code, notes, and snippets.

@hoffrocket
Last active December 14, 2015 02:59
Show Gist options
  • Save hoffrocket/5017996 to your computer and use it in GitHub Desktop.
Save hoffrocket/5017996 to your computer and use it in GitHub Desktop.
Buffered FileTailer in scala.
import java.io.{File, RandomAccessFile}
import java.nio.{ByteBuffer, CharBuffer}
import java.nio.charset.Charset
/**
* Read lines from the end of a file.
*
* Partial lines that don't terminate with a newline will be lost
* Lines bigger than the buffer size will also be lost
*/
class FileTailer(val path: String) {
val charset = Charset.forName("utf-8")
val buffer = ByteBuffer.allocate(8192)
var charBuffer: CharBuffer = null
val file = {
val f = new File(path)
val raf = new RandomAccessFile(f, "r")
raf.seek(math.max(0, f.length - buffer.capacity))
raf
}
def readLine: CharSequence = {
if (charBuffer == null || !charBuffer.hasRemaining) {
buffer.clear
file.getChannel.read(buffer)
buffer.flip
charBuffer = charset.decode(buffer)
}
var foundNewLine = false
charBuffer.mark
while (charBuffer.hasRemaining && !foundNewLine) {
if (charBuffer.get == '\n') {
foundNewLine = true
}
}
if (foundNewLine) {
val copy = charBuffer.duplicate
copy.limit(copy.position - 1)
copy.reset
copy
} else {
null
}
}
def close = file.close
}
@hoffrocket
Copy link
Author

Apparently, FileInputStream.skip may or may not work for a "variety of reasons" http://docs.oracle.com/javase/6/docs/api/java/io/FileInputStream.html#skip(long)

RandomAccessFile seeks as expected, but the readLine method is unbuffered and doesn't seem to correctly handle unicode.

Inspired by http://stackoverflow.com/questions/4305094/java-reading-strings-from-a-random-access-file-with-buffered-input

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment