How can I read a file to an InputStream then write it into an OutputStream in Scala?

16,565

Solution 1

You could do this:

Iterator 
.continually (input.read)
.takeWhile (-1 !=)
.foreach (output.write)

Solution 2

If this is slow:

Iterator 
.continually (input.read)
.takeWhile (-1 !=)
.foreach (output.write)

you can expand it:

val bytes = new Array[Byte](1024) //1024 bytes - Buffer size
Iterator
.continually (input.read(bytes))
.takeWhile (-1 !=)
.foreach (read=>output.write(bytes,0,read))
output.close()

Solution 3

Assignment statements always return Unit in Scala, so read = input.read returns Unit, which never equals -1. You can do it like this:

while ({read = input.read; read != -1}) {
  output.write(read)
}

Solution 4

def stream(inputStream: InputStream, outputStream: OutputStream) =
{
  val buffer = new Array[Byte](16384)

  def doStream(total: Int = 0): Int = {
    val n = inputStream.read(buffer)
    if (n == -1)
      total
    else {
      outputStream.write(buffer, 0, n)
      doStream(total + n)
    }
  }

  doStream()
}
Share:
16,565
Maurício Linhares
Author by

Maurício Linhares

Java, Ruby, Objective-C and Scala developer who loves taking pictures, answering questions, playing boardgames and traveling. You can find more of my writings at my personal blog.

Updated on June 03, 2022

Comments

  • Maurício Linhares
    Maurício Linhares about 2 years

    I'm trying to use basic Java code in Scala to read from a file and write to an OutputStream, but when I use the usual while( != -1 ) in Scala gives me a warning "comparing types of Unit and Int with != will always yield true".

    The code is as follows:

        val file = this.cache.get(imageFileEntry).getValue().asInstanceOf[File]
        response.setContentType( "image/%s".format( imageDescription.getFormat() ) )
    
        val input = new BufferedInputStream( new FileInputStream( file ) )
        val output = response.getOutputStream()
    
        var read : Int = -1
    
        while ( ( read = input.read ) != -1 ) {
            output.write( read )
        }
    
        input.close()
        output.flush()
    

    How am I supposed to write from an input stream to an output stream in Scala?

    I'm mostly interested in a Scala-like solution.

  • Maurício Linhares
    Maurício Linhares almost 13 years
    You can't have more than one statement in a while/if/for clause. This code yields a compilation error. But thanks for the assignment thing, i thought it would behave like java.
  • AndreasScheinert
    AndreasScheinert almost 13 years
    Hi Mauricio! Yes the {} are the key point in his example. Let's call them a block. Everything inside will be executed and the result is eventually returned having the type of the last expression.
  • Maurício Linhares
    Maurício Linhares almost 13 years
    Ok, this looks like a real Scala solution, but is this continually call load the file into memory or is it going to call this function as the foreach loop runs? Also, can you elaborate a bit on this takeWhile method? Why didn't you have to use the _ parameter or define a parameter yourself?
  • Kim Stebel
    Kim Stebel almost 13 years
    sorry, added the braces a little late;)
  • Daniel C. Sobral
    Daniel C. Sobral almost 13 years
    @Maurício It's an iterator, so everything is done only on-demand. Until foreach, nothing really happens -- you just get new Iterator objects that do some pre-processing before next or hasNext. On foreach, an output.write is executed for each input.read, and then its value is promptly forgotten and garbage collected.
  • gerferra
    gerferra almost 13 years
    It would be nice to have a version using the scala-io incubator project
  • Christopher
    Christopher almost 12 years
    This is a better solution. The above solutions are horribly slow. One call per byte read of overhead? Really? How is that acceptable in a bulk data mover?
  • lyomi
    lyomi about 7 years
    It should be noted that for the maximum performance, both input and output stream should have been buffered (using Buffered{Input,Output}Stream). It will still be significantly slower than the non-Scala-like way
  • foxtrotuniform6969
    foxtrotuniform6969 almost 5 years
    This is assuming that you're ok just reading 1024 bytes though. What if I don't know how much I need to read until I reach something like a delineator?