One aspect of resources in Scala-IO that can cause problems is the construction of resource objects. The factory methods that are provided in the Resource object each have a lazy parameter for opening the underlying resource. However a common error developers can make is to pass in the already open resource to the method which has multiple problems.
Consider:
1 2 3 4 5 6 7 8 9 | import scalax.io. _ val stream = new java.io.FileOutputStream( "somefile.txt" ) val output = Resource.fromOutputStream(stream) output write "hey " // boom, stream was closed last write // and the stream cannot be reopened. output write "how's it going?" |
- the stream is open and if the resource object is not closed you will have a resource leak
- since the stream is opened the resource can only be used once since it will be closed after each use.
The correct way to create the resource would be to change val to def so that the stream is only created on demand and therefore there will be no chance of a resource leak. The following is the correct example:
1 2 3 4 5 6 7 8 9 10 11 12 | import scalax.io. _ def stream = new java.io.FileOutputStream( "somefile.txt" ) val output = Resource.fromOutputStream(stream) output write "hey " // the second write will now work. However since // the underlying resource is a FileOutputStream // the file will contain just "how's it going" output write "how's it going?" println(Resource.fromFile( "somefile.txt" ).string) |
This anti-pattern is also a risk when using the converter methods in the JavaConverters object. (A future post will look into this in more detail.) The following example shows the anti-pattern in effect:
1 2 3 4 5 6 7 8 9 | import scalax.io. _ import JavaConverters. _ val output = new java.io.FileOutputStream( "somefile.txt" ).asOutput output write "hey " // Next line will cause exception because // stream is closed. output write "how's it going?" |
No comments:
Post a Comment