Scala: InputStream to Array[Byte]

后端 未结 11 842
臣服心动
臣服心动 2021-02-02 06:01

With Scala, what is the best way to read from an InputStream to a bytearray?

I can see that you can convert an InputStream to char array

Source.fromInput         


        
相关标签:
11条回答
  • 2021-02-02 06:41

    How about:

    Stream.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray
    

    Update: Use LazyList instead of Stream (since 2.13.x deprecated)

    LazyList.continually(is.read).takeWhile(_ != -1).map(_.toByte).toArray
    
    0 讨论(0)
  • 2021-02-02 06:41

    How about buffered version of solution based on streams plus ByteArraOutputStream to minimize boilerplate around final array growing?

    val EOF: Int = -1
    
    def readBytes(is: InputStream, bufferSize: Int): Array[Byte] = {
      val buf = Array.ofDim[Byte](bufferSize)
      val out = new ByteArrayOutputStream(bufferSize)
    
      Stream.continually(is.read(buf)) takeWhile { _ != EOF } foreach { n =>
        out.write(buf, 0, n)
      }
    
      out.toByteArray
    }
    
    0 讨论(0)
  • 2021-02-02 06:43

    With Scala IO, this should work:

    def inputStreamToByteArray(is: InputStream): Array[Byte] = 
       Resource.fromInputStream(in).byteArray
    
    0 讨论(0)
  • 2021-02-02 06:47

    Just removed bottleneck in our server code by replacing

    Stream.continually(request.getInputStream.read()).takeWhile(_ != -1).map(_.toByte).toArray
    

    with

    org.apache.commons.io.IOUtils.toByteArray(request.getInputStream)
    

    Or in pure Scala:

    def bytes(in: InputStream, initSize: Int = 8192): Array[Byte] = {
      var buf = new Array[Byte](initSize)
      val step = initSize
      var pos, n = 0
      while ({
        if (pos + step > buf.length) buf = util.Arrays.copyOf(buf, buf.length << 1)
        n = in.read(buf, pos, step)
        n != -1
      }) pos += n
      if (pos != buf.length) buf = util.Arrays.copyOf(buf, pos)
      buf
    }
    

    Do not forget to close an opened input stream in any case:

    val in = request.getInputStream
    try bytes(in) finally in.close()
    
    0 讨论(0)
  • 2021-02-02 06:47

    In a similar vein to Eastsun's answer... I started this as a comment, but it ended up getting just a bit to long!

    I'd caution against using Stream, if holding a reference to the head element then streams can easily consume a lot of memory.

    Given that you're only going to read in the file once, then Iterator is a much better choice:

    def inputStreamToByteArray(is: InputStream): Array[Byte] =
      Iterator continually is.read takeWhile (-1 !=) map (_.toByte) toArray
    
    0 讨论(0)
  • 2021-02-02 06:50

    With better-files, you can simply do is.bytes

    0 讨论(0)
提交回复
热议问题