Support File.readBytes when reported file length is less than actual
After reading 'length' bytes from a file, check if there's extra content available and read it into a resizable buffer, then append it after the first 'length' bytes. #KT-33864
This commit is contained in:
@@ -72,7 +72,31 @@ public fun File.readBytes(): ByteArray = inputStream().use { input ->
|
||||
remaining -= read
|
||||
offset += read
|
||||
}
|
||||
if (remaining == 0) result else result.copyOf(offset)
|
||||
if (remaining > 0) return@use result.copyOf(offset)
|
||||
|
||||
val extraByte = input.read()
|
||||
if (extraByte == -1) return@use result
|
||||
|
||||
// allocation estimate: (RS + DBS + max(ES, DBS + 1)) + (RS + ES),
|
||||
// where RS = result.size, ES = extra.size, DBS = DEFAULT_BUFFER_SIZE
|
||||
// when RS = 0, ES >> DBS => DBS + DBS + 1 + ES + ES = 2DBS + 2ES
|
||||
// when RS >> ES, ES << DBS => RS + DBS + DBS+1 + RS + ES = 2RS + 2DBS + ES
|
||||
val extra = ExposingBufferByteArrayOutputStream(DEFAULT_BUFFER_SIZE + 1)
|
||||
extra.write(extraByte)
|
||||
input.copyTo(extra)
|
||||
|
||||
val resultingSize = result.size + extra.size()
|
||||
if (resultingSize < 0) throw OutOfMemoryError("File $this is too big to fit in memory.")
|
||||
|
||||
return@use extra.buffer.copyInto(
|
||||
destination = result.copyOf(resultingSize),
|
||||
destinationOffset = result.size,
|
||||
startIndex = 0, endIndex = extra.size()
|
||||
)
|
||||
}
|
||||
|
||||
private class ExposingBufferByteArrayOutputStream(size: Int) : ByteArrayOutputStream(size) {
|
||||
val buffer: ByteArray get() = buf
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user