Is there a nice, safe, quick way to write an InputStream to a File in Scala?
Asked Answered
O

4

22

Specifically, I'm saving a file upload to local file in a Lift web app.

Ogawa answered 6/5, 2010 at 16:16 Comment(0)
A
20

If it's a text file, and you want to limit yourself to Scala and Java, then using scala.io.Source to do the reading is probably the fastest--it's not built in, but easy to write:

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 }
}

But if you need other libraries anyway, you can make your life even easier by using them (as Michel illustrates).

(P.S.--in Scala 2.7, getLines should not have a () after it.)

(P.P.S.--in old versions of Scala, getLines did not remove the newline, so you need to print instead of println.)

Autacoid answered 6/5, 2010 at 17:50 Comment(0)
O
42

With Java 7 or later you can use Files from the new File I/O:

Files.copy(from, to)

where from and to can be Paths or InputStreams. This way, you can even use it to conveniently extract resources from applications packed in a jar.

Orndorff answered 21/2, 2013 at 15:39 Comment(4)
Do you need to call close after this?Desirable
Files itself does not represent a file, but is a static collection of I/O functions, so it does not require to be closed. Files.copy does not manipulate the streams you pass in, so whatever you may need to close there, you must close yourself.Orndorff
can't call this method because of ``` Error:(25, 11) overloaded method value copy with alternatives: (x$1: java.nio.file.Path,x$2: java.io.OutputStream)Long <and> (x$1: java.io.InputStream,x$2: java.nio.file.Path,x$3: java.nio.file.CopyOption*)Long <and> (x$1: java.nio.file.Path,x$2: java.nio.file.Path,x$3: java.nio.file.CopyOption*)java.nio.file.Path cannot be applied to (java.io.InputStream, java.io.File) Files.copy(content, distTemporaryFile) ```Berndt
It seems that you are passing an File as second argument whereas the functions expects a Path. You could File.toPath() to obtain the Path.Orndorff
A
20

If it's a text file, and you want to limit yourself to Scala and Java, then using scala.io.Source to do the reading is probably the fastest--it's not built in, but easy to write:

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 }
}

But if you need other libraries anyway, you can make your life even easier by using them (as Michel illustrates).

(P.S.--in Scala 2.7, getLines should not have a () after it.)

(P.P.S.--in old versions of Scala, getLines did not remove the newline, so you need to print instead of println.)

Autacoid answered 6/5, 2010 at 17:50 Comment(0)
U
9

I don't know about any Scala specific API, but since Scala is fully compatible to Java you can use any other library like Apache Commons IO and Apache Commons FileUpload.

Here is some example code (untested):

//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))
Unknowing answered 6/5, 2010 at 17:13 Comment(0)
O
4

The inputToFile method given above doesn't work well with binary files like .pdf files. It throws a runtime exception while attempting to decode the file into string. What worked for me was this:

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()
}
Odont answered 8/10, 2014 at 12:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.