Insbesondere speichere ich einen Datei-Upload in eine lokale Datei in einer Lift Web App.Gibt es eine nette, sichere und schnelle Möglichkeit, einen InputStream in Scala in eine Datei zu schreiben?
Antwort
Wenn es sich um eine Textdatei ist, und Sie möchten sich Scala und Java beschränken, dann scala.io.Source
mit dem Lesen zu tun, ist wahrscheinlich die fastest-- es ist nicht eingebaut, aber einfach zu schreiben:
def inputToFile(is: java.io.InputStream, f: java.io.File) {
val in = scala.io.Source.fromInputStream(is)
val out = new java.io.PrintWriter(f)
try { in.getLines().foreach(out.println(_)) }
finally { out.close }
}
aber wenn Sie andere Bibliotheken sowieso benötigen, können Sie Ihr Leben noch einfacher machen, indem man sich mit (wie Michel zeigt).
(PS - in Scala 2.7, getLines
sollte keine ()
nach ihm.)
(PPS - in alten Versionen von Scala, getLines
nicht das Newline entfernen, so dass Sie print
brauchen statt . println
)
Ich weiß nichts über Scala-spezifische API, aber da Scala vollständig kompatibel zu Java ist, können Sie jede andere Bibliothek wie Apache Commons IO und Apache Commons FileUpload verwenden. Hier
ist einige Beispiel-Code (ungetestet):
//using Commons IO:
val is = ... //input stream you want to write to a file
val os = new FileOutputStream("out.txt")
org.apache.commons.io.IOUtils.copy(is, os)
os.close()
//using Commons FileUpload
import javax.servlet.http.HttpServletRequest
import org.apache.commons.fileupload.{FileItemFactory, FileItem}
import apache.commons.fileupload.disk.DiskFileItemFactory
import org.apache.commons.fileupload.servlet.ServletFileUpload
val request: HttpServletRequest = ... //your HTTP request
val factory: FileItemFactory = new DiskFileItemFactory()
val upload = new ServletFileUpload(factory)
val items = upload.parseRequest(request).asInstanceOf[java.util.List[FileItem]]
for (item <- items) item.write(new File(item.getName))
Mit Java 7 können Sie verwenden Files
from the new File I/O:
Files.copy(from, to)
wo from
und to
kann Path
s oder InputStream
s sein. Auf diese Weise können Sie sogar Ressourcen aus in einem Jar gepackten Anwendungen bequem extrahieren.
Müssen Sie danach 'close' anrufen? – Jus12
'Files' selbst stellt keine Datei dar, sondern ist eine statische Sammlung von I/O-Funktionen, so dass es nicht geschlossen werden muss. 'Files.copy' manipuliert nicht die Datenströme, die Sie übergeben, also müssen Sie sich schließen, egal was Sie dort schließen müssen. – notan3xit
Die oben angegebene inputToFile-Methode funktioniert nicht gut mit Binärdateien wie .pdf-Dateien. Beim Versuch, die Datei in eine Zeichenfolge zu dekodieren, wird eine Laufzeitausnahme ausgelöst. Was für mich funktionierte, war folgendes:
def inputStreamToFile(inputStream: java.io.InputStream, file: java.io.File) = {
val fos = new java.io.FileOutputStream(file)
fos.write(
Stream.continually(inputStream.read).takeWhile(-1 !=).map(_.toByte).toArray
)
fos.close()
}
Dieser Code verliert Zeilenwechselzeichen. – shinichy
@shinichy - Das Verhalten hat sich geändert, seit ich die Antwort geschrieben habe. Ich habe es aktualisiert. –
Danke für die Aktualisierung! – shinichy