Convert InputStream to byte array in Java

前端 未结 30 3575
無奈伤痛
無奈伤痛 2020-11-21 12:08

How do I read an entire InputStream into a byte array?

30条回答
  •  闹比i
    闹比i (楼主)
    2020-11-21 12:53

    Solution in Kotlin (will work in Java too, of course), which includes both cases of when you know the size or not:

        fun InputStream.readBytesWithSize(size: Long): ByteArray? {
            return when {
                size < 0L -> this.readBytes()
                size == 0L -> ByteArray(0)
                size > Int.MAX_VALUE -> null
                else -> {
                    val sizeInt = size.toInt()
                    val result = ByteArray(sizeInt)
                    readBytesIntoByteArray(result, sizeInt)
                    result
                }
            }
        }
    
        fun InputStream.readBytesIntoByteArray(byteArray: ByteArray,bytesToRead:Int=byteArray.size) {
            var offset = 0
            while (true) {
                val read = this.read(byteArray, offset, bytesToRead - offset)
                if (read == -1)
                    break
                offset += read
                if (offset >= bytesToRead)
                    break
            }
        }
    

    If you know the size, it saves you on having double the memory used compared to the other solutions (in a brief moment, but still could be useful). That's because you have to read the entire stream to the end, and then convert it to a byte array (similar to ArrayList which you convert to just an array).

    So, if you are on Android, for example, and you got some Uri to handle, you can try to get the size using this:

        fun getStreamLengthFromUri(context: Context, uri: Uri): Long {
            context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.SIZE), null, null, null)?.use {
                if (!it.moveToNext())
                    return@use
                val fileSize = it.getLong(it.getColumnIndex(MediaStore.MediaColumns.SIZE))
                if (fileSize > 0)
                    return fileSize
            }
            //if you wish, you can also get the file-path from the uri here, and then try to get its size, using this: https://stackoverflow.com/a/61835665/878126
            FileUtilEx.getFilePathFromUri(context, uri, false)?.use {
                val file = it.file
                val fileSize = file.length()
                if (fileSize > 0)
                    return fileSize
            }
            context.contentResolver.openInputStream(uri)?.use { inputStream ->
                if (inputStream is FileInputStream)
                    return inputStream.channel.size()
                else {
                    var bytesCount = 0L
                    while (true) {
                        val available = inputStream.available()
                        if (available == 0)
                            break
                        val skip = inputStream.skip(available.toLong())
                        if (skip < 0)
                            break
                        bytesCount += skip
                    }
                    if (bytesCount > 0L)
                        return bytesCount
                }
            }
            return -1L
        }
    

提交回复
热议问题