I have a class which functions something like this
class OutputFile(name: String, index: Int = 0){
val localFile = File.createTempFile(name, ".gz")
localFile.deleteOnExit()
val localFileOut =new FileOutputStream(localFile)
private[this] var bytesWritted: Int = 0
def write(line: Bytes): OutputFile = {
if(bytesWritten > SOMESIZE) flush //this function uploads the file to a different location and closes the localfile and localFileOut
try{
writeLine(line) //this writes the line to the localfile
this
}catch{
//If the file had been closed by flush create a new object
case IOException =>
val outFile = new OutputFile(name, index+1)
outfile.write(line)
outfile
}
//Other functions like flush and writeLine
}
However now I cannot use this object with an immutable. Coming from a java background it is difficult for me to convert this class to an immutable style. In java code we could have just used a global variable for the output streams and changed it whenever required.
Is there some better method that I am definitely missing to implement such a scenario.
To make the workflow of
OutputFile
immutable, every call has to return a new immutable instance, not just the call that swaps outfiles:I've added a companion object
OutputFile
so that the actual constructor is the constructor for the new immutable instance and to abstract the opening of a new stream.Each call to write creates a new
OutputFile
and tracks how many bytes have been written to the current file. Once theTHRESHOLD
has been reached, the file is flushed and a new instance with a new stream is returned. TheIOException
is no longer responsible for triggering the new file (that's just done when we know we've flushed), instead it's a retry with a max of 3 attempts.A final word of caution: This class is still inherently stateful, since it does deal with File I/O. While this tries to pretend there is no state, it makes the assumption that write will never be called twice on a single instance.