2009-11-19 21 views
16

Ich benutze Scala Source.fromFile aber ich kann nicht scheinen, eine nette Möglichkeit zu finden, es close der zugrunde liegenden InputStream zu bekommen, sobald die Datei gelesen worden ist.Warum schließt Scala Source den zugrunde liegenden InputStream nicht?

Hier ist mein Code, der mit einem AssertionError fehlschlägt, weil die Datei nicht gelöscht werden kann.

def main(args : Array[String]) : Unit = { 

    val myFile = new File("c:/tmp/doodah.txt") 
    var src = Source.fromFile(myFile) 
    src.getLines.foreach(l => print(l)) 

    val deleted: Boolean = myFile.delete 

    assert (deleted , "File was not deleted - maybe the stream hasn't been closed in Source") 

    } 

Quelle eine Methode hat reset jedoch alle genannt, dass dies tut, ist die Quelle, aus der Datei neu zu erstellen.

Intern Source erstellt eine zugrunde liegende BufferedSource, die eine close Methode hat. Dies wird jedoch nicht von der Quelle angezeigt.

Ich hoffe, dass Source das Datei-Handle freigeben würde, sobald der Inhalt der Datei gelesen wurde, aber das scheint das nicht zu tun.

Die beste Problemumgehung, die ich bis jetzt gesehen habe, besteht darin, die Source zu einer BufferedSource im Wesentlichen zu werfen und close zu rufen.

try { 
    src.getLines.foreach(l => print(l)) 
} 
finally src match { case b: scala.io.BufferedSource => b.close } 

Alternativ könnte ich eine Source von einem InputStream erstellen und die Schließung selbst verwalten.

Allerdings scheint dies etwas schmutzig. Wie soll das Dateihandle freigegeben werden, wenn Source verwendet wird?

Antwort

14

Scala.io._ ist ein Barebone-Hack, der ausschließlich zum Unterstützen der XML-Bibliothek und des Compilers erstellt wurde. Es ist schlecht gestaltet und leidet unter vielen Problemen. Scala 2.8 wird eine verbesserte Version davon anbieten, obwohl es kaum etwas gibt, worüber man nach Hause schreiben könnte.

Es gibt eine fortwährende dritte Bemühung von interessierten Parteien, eine Sound Scala I/O Bibliothek zu entwickeln. Es zielt darauf ab, die Lehren aus dem JDK7-I/O-Redesign mitzunehmen und gleichzeitig eine Scala-ish-API bereitzustellen.

In der Zwischenzeit ... verwenden Sie Java-Bibliotheken, wenn Ihre Anwendung auf die Designprobleme der vorliegenden Bibliothek stößt.

+1

@DCS ein Link zu oder Name der "laufenden Bemühungen Dritter"? –

+1

@ C.W. HolemanII [Scala I/O] (https://github.com/scala-incubator/scala-io), die leider nach zweieinhalb Jahren immer noch nicht Teil der Standardbibliothek ist. –

6

Funktioniert in Scala 2.8.x mit ein wenig Modifikation. "GetLines" -> "getLines()"

... 
src.getLines().foreach(l => print(l)) 
... 

scala.io.Source in 2.8.x besser durchdacht als sein Pendant in 2.7.x und es richtig schließt die Input.

+0

Warum müssen Sie verwenden, um die leeren Pars Relay ist in 2.8? – pjp

+1

Die Methode "getLines" hat ein Argument in 2.8, das standardmäßig auf das EOL-Zeichen der Plattform verweist. Beachten Sie, dass in 2.8 –

+0

Standardargumente hinzugefügt wurden. Beachten Sie, dass Source.getLines in Scala 2.9.0.1 momentan unterbrochen ist: https: //issues.scala-lang.org/browse/SI-4662 –

4

soweit ich kann iio.Source ist immer noch in 2.8 gebrochen (Verbindungen sind durchgesickert etc), so dass Menschen davon abgeraten werden, es zu verwenden.

Als David schlug oben, bis der Ersatz lib http://github.com/scala-incubator/scala-io verschmolzen wird (wahrscheinlich nach 2.8) die beste Wahl auf reinem Java-Libs wie Apache commons-io usw.

+0

UPD: Das verlinkte Problem wurde vor fast einem Jahr behoben –

Verwandte Themen