Reading a file, handling a stream of data, theoretically those are not ultimately complex operations, but they require some special attention. Every stream, every resource needs to be closed. Closed to free descriptors, memory, or maybe just a TCP port. How to design the code, so that a resource will always be properly closed, even when the programmer forgets?

Going back in time

For start, let’s remind ourselves how resource handling looked like in the C-times. First, you start with opening the file:

#include <stdio.h>

// ...

FILE * file = fopen("test.txt", "r");

Returned value, file , allows to control the stream of data. Usually you would perform some fread ‘s or getc to retrieve the file content, and end the whole operation with:

fclose(file);

Perfect solution? Not really, you have to remember to close the file manually, even when some intermediate operations will return errors.

Java Virtual Machine?

Does it get better in Java? Well, depends on a version. In older ones you still have to manually close resources.

BufferedReader br = new BufferedReader(new FileReader("test.txt")); try {

String line = br.readLine();

// ...

} finally {

br.close();

}

However, you get the try-catch-finally statements guaranteeing that finally block will be automatically executed even when exception is thrown. But, from Java 7 you can leverage the “try-with-resources” construction:

try(BufferedReader br = new BufferedReader(new FileReader("test.txt"))) {

String line = br.readLine();

// ...

}

Better? Definitely! Java 7 introduced an AutoCloseable interface. Every class implementing it can be used with “try-with-resources”. You don’t need to manually close your file, it will get auto closed after the processing block ends.

Side note: From Java 7 you can read files easier e.g. just by using Files.readAllLines(...)

Scala

How does it look in Scala, well…

val source = scala.io.Source.fromFile("test.txt")

val lines = try source.mkString finally source.close()

You can use other classes instead of the BufferedReader , but how about the “try-with-resources” ? Unfortunately there is no built-in, ready to use equivalent. You can implement it on your own, however additional project was created to solve this issue, the scala-arm (Scala Automatic Resource Management).

import resource._ val mr = managed(new java.io.FileInputStream("test.txt")

for(r <- mr ) {

// do some reading...

}

scala-arm APIs produce the ManagedResource objects. After the for block ends, the resource will get closed.

Advantages? Resource gets auto closed and what is more, your API can return object, which after processing ( foreach or map ) will close automatically. API user does not have to worry about that!

FP world

Functional Programming world created the Bracket pattern already many years ago. It’s intended to use with resources which require acquiring and releasing actions. Let’s take a look how it looks in Cats-effect:

IO(new BufferedReader(new FileReader(file))).bracket {

in =>

IO(in.readLine())

} { in =>

IO(in.close())

}

The first bracket block is responsible for resource usage, and the second one for closing. Advantages? It’s pure of course ;) It works with cats IO Monad (in short: type designed to handle operations which may include unpure side effects) and the release function is guaranteed to run even when errors occur. Cats library offers however, one more class for resource handling, named… Resource .

import cats.effect._ val acquire = IO { // it touches file system so let's wrap it in IO

scala.io.Source.fromString("Hello world")

}

Resource.fromAutoCloseable(acquire)

.use(source => IO(println(source.mkString))) //use ~ map on resource

.unsafeRunSync() // it is lazily evaluated, you need to run

Resource supports the java AutoCloseable which is quite handy. You don’t need to define the release / close methods, only the acquirement and the actual usage. After processing is finished, the underlying resource will get closed.

Summary