java.io.IOException when wrapping io.Source.fromFile

98 views
Skip to first unread message

Andy C

unread,
Jun 11, 2013, 5:42:25 PM6/11/13
to scala-user
Hi,

I am using this wrapper function to ensure I release file handlers after reading files.

scala>   def manageSource[T](s:io.Source)(f:io.Source=>T)=
     |   {
     |     val t=f(s)
     |     s.close()
     |     t
     |   }
manageSource: [T](s: scala.io.Source)(f: scala.io.Source => T)T


Then reading file looks like that:

scala> manageSource(io.Source.fromFile("myfile"))(_.getLines.toList)

However, when I want just an iterator:

scala> manageSource(io.Source.fromFile("myfile"))(_.getLines)

the thing crashes in runtime:

java.io.IOException: Bad file descriptor
    at java.io.FileInputStream.readBytes(Native Method)
    at java.io.FileInputStream.read(FileInputStream.java:220)
    at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:264)
    at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:306)
    at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:158)
    at java.io.InputStreamReader.read(InputStreamReader.java:167)
    at java.io.BufferedReader.fill(BufferedReader.java:136)
    at java.io.BufferedReader.readLine(BufferedReader.java:299)
    at java.io.BufferedReader.readLine(BufferedReader.java:362)
    at scala.io.BufferedSource$BufferedLineIterator.hasNext(BufferedSource.scala:67)
    at scala.collection.Iterator$$anon$10.hasNext(Iterator.scala:308)
    at scala.collection.Iterator$class.toString(Iterator.scala:1152)
    at scala.collection.AbstractIterator.toString(Iterator.scala:1156)
    at scala.runtime.ScalaRunTime$.scala$runtime$ScalaRunTime$$inner$1(ScalaRunTime.scala:328)
    at scala.runtime.ScalaRunTime$.stringOf(ScalaRunTime.scala:333)
    at scala.runtime.ScalaRunTime$.replStringOf(ScalaRunTime.scala:341)
    at .<init>(<console>:10)


I have hard time understanding why it happens. Is it because we close the file before exhausting the iterator?

Please advise,
Andy

Alex Cruise

unread,
Jun 12, 2013, 1:19:46 AM6/12/13
to Andy C, scala-user
On Tue, Jun 11, 2013 at 2:42 PM, Andy C <andy.c...@gmail.com> wrote:
I have hard time understanding why it happens. Is it because we close the file before exhausting the iterator?

Yes. Iterators are inherently stateful. The Iterator produced by Source, if it is to avoid buffering the entire contents of the file, must hold on to the file descriptor and read from it on demand.

The version that calls .toList inside the closure has already exhausted the iterator before the descriptor is closed. :)

-0xe1a
Reply all
Reply to author
Forward
0 new messages