FileSourceProvider.kt
TLDR
The FileSourceProvider
class in the shark
package is responsible for providing access to a file as both streaming and random access sources.
Methods
openStreamingSource
This method returns a BufferedSource
object that allows for streaming read access to the file.
openRandomAccessSource
This method returns a RandomAccessSource
object that allows for random access read access to the file. It reads the file in chunks, stores the chunks in an internal buffer, and provides the requested data in a Buffer
object.
Classes
FileSourceProvider
This class implements the DualSourceProvider
interface and provides access to a file as both streaming and random access sources. It uses Okio
to create a BufferedSource
object for streaming access and a custom RandomAccessSource
implementation for random access.
package shark
import java.io.File
import java.io.RandomAccessFile
import kotlin.math.min
import okio.Buffer
import okio.BufferedSource
import okio.Okio
class FileSourceProvider(private val file: File) : DualSourceProvider {
override fun openStreamingSource(): BufferedSource = Okio.buffer(Okio.source(file.inputStream()))
override fun openRandomAccessSource(): RandomAccessSource {
val randomAccessFile = RandomAccessFile(file, "r")
val arrayBuffer = ByteArray(500_000)
return object : RandomAccessSource {
override fun read(
sink: Buffer,
position: Long,
byteCount: Long
): Long {
val byteCountInt = byteCount.toInt()
randomAccessFile.seek(position)
var totalBytesRead = 0
val maxRead = arrayBuffer.size
while (totalBytesRead < byteCount) {
val toRead = min(byteCountInt - totalBytesRead, maxRead)
val bytesRead = randomAccessFile.read(arrayBuffer, 0, toRead)
if (bytesRead == -1) {
check(totalBytesRead != 0) {
"Did not expect to reach end of file after reading 0 bytes"
}
break
}
sink.write(arrayBuffer, 0, bytesRead)
totalBytesRead += bytesRead
}
return totalBytesRead.toLong()
}
override fun close() {
try {
randomAccessFile.close()
} catch (ignored: Throwable) {
SharkLog.d(ignored) { "Failed to close file, ignoring" }
}
}
}
}
}