Plus précisément, j'importe un fichier téléchargé dans un fichier local dans une application Web Lift.Existe-t-il un moyen simple, sûr et rapide d'écrire un InputStream dans un fichier dans Scala?
Répondre
Si c'est un fichier texte, et que vous voulez vous limiter à Scala et Java, puis en utilisant scala.io.Source
pour faire la lecture est probablement le fastest-- il n'est pas construit, mais facile à écrire:
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 }
}
mais si vous avez besoin d'autres bibliothèques de toute façon, vous pouvez vous rendre la vie encore plus facile en les utilisant (comme Michel illustre).
(PS - Scala 2.7, getLines
ne devrait pas avoir un ()
après.)
(PPS - dans les anciennes versions de Scala, getLines
n'a pas enlevé la nouvelle ligne, donc vous devez print
au lieu de . println
)
Je ne connais aucune API spécifique à Scala, mais comme Scala est entièrement compatible avec Java, vous pouvez utiliser n'importe quelle autre bibliothèque comme Apache Commons IO et Apache Commons FileUpload.
Voici quelques exemples de code (non testé):
//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))
Avec Java 7, vous pouvez utiliser Files
from the new File I/O:
Files.copy(from, to)
où from
et to
peut être Path
s ou InputStream
s. De cette façon, vous pouvez même l'utiliser pour extraire facilement des ressources d'applications contenues dans un pot.
Avez-vous besoin d'appeler 'close' après cela? – Jus12
'Files' lui-même ne représente pas un fichier, mais est une collection statique de fonctions d'E/S, il n'a donc pas besoin d'être fermé. 'Files.copy' ne manipule pas les flux que vous transmettez, donc tout ce dont vous avez besoin de fermer, vous devez vous fermer. – notan3xit
La méthode inputToFile donnée ci-dessus ne fonctionne pas bien avec les fichiers binaires tels que les fichiers .pdf. Il lance une exception d'exécution lors de la tentative de décodage du fichier en chaîne. Ce qui a fonctionné pour moi était ceci:
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()
}
ce code perd les caractères de nouvelle ligne. – shinichy
@shinichy - Le comportement a changé depuis que j'ai écrit la réponse. Je l'ai mis à jour. –
Merci pour la mise à jour! – shinichy