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()
}
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, 2022Comments
-
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 almost 13 yearsYou 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 almost 13 yearsHi 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 almost 13 yearsOk, 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 almost 13 yearssorry, added the braces a little late;)
-
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 newIterator
objects that do some pre-processing beforenext
orhasNext
. Onforeach
, anoutput.write
is executed for eachinput.read
, and then its value is promptly forgotten and garbage collected. -
gerferra almost 13 yearsIt would be nice to have a version using the scala-io incubator project
-
Christopher almost 12 yearsThis 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 about 7 yearsIt 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 almost 5 yearsThis 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?