The whole point of reading a file is to gain state that you didn't have before. I don't, therefore, exactly understand what you're after.
One can pretend that one has the entire universe as an input (and output) parameter and create a "functional" analog, but I've never seen a clear demonstration that this has any superior characteristics.
Most functional data structures allow you to abstract over copy number. For example, a list lets you extend operations on an individual element to all elements in convenient ways (map, reduce, etc.). But when you want to read a file, you need to abstract over data type, and furthermore, you don't actually want it completely abstract--you want to match some sort of template that you expect. How you specify this template--and what to do on error conditions--is, I suspect, the core of your binary file reading challenge.
(Note also that unless you're running on one of those highly multicore Sun boxes (T2000 for example), you don't need immutability for safety since one thread is plenty fast enough to handle all of the low-level input processing.)
One possibility is to treat binary file reading as a parsing problem. Scala doesn't have a robust library for that at the moment, but see this thread for a nice bit of code written by Paul Phillips that helps in this regard.
Another possibility is to create some sort of template yourself, like
List(classOf[Float],classOf[Int],classOf[String])
and then write something that parses that stream sequentially with match statements:
val FloatClass = classOf[Float]
listEntry match {
case FloatClass => // Read float
...
}
These sorts of things make the job of reading binary files a lot easier, and it is at least sort of functional, since you can map your input stream of bytes into a List[Any]
and then use pattern matching to grab out the data that you want.