1 package shark 2 3 import java.io.File 4 import java.io.RandomAccessFile 5 import kotlin.math.min 6 import okio.Buffer 7 import okio.BufferedSource 8 import okio.Okio 9 10 class FileSourceProvider(private val file: File) : DualSourceProvider { openStreamingSourcenull11 override fun openStreamingSource(): BufferedSource = Okio.buffer(Okio.source(file.inputStream())) 12 13 override fun openRandomAccessSource(): RandomAccessSource { 14 15 val randomAccessFile = RandomAccessFile(file, "r") 16 17 val arrayBuffer = ByteArray(500_000) 18 19 return object : RandomAccessSource { 20 override fun read( 21 sink: Buffer, 22 position: Long, 23 byteCount: Long 24 ): Long { 25 val byteCountInt = byteCount.toInt() 26 randomAccessFile.seek(position) 27 var totalBytesRead = 0 28 val maxRead = arrayBuffer.size 29 while (totalBytesRead < byteCount) { 30 val toRead = min(byteCountInt - totalBytesRead, maxRead) 31 val bytesRead = randomAccessFile.read(arrayBuffer, 0, toRead) 32 if (bytesRead == -1) { 33 check(totalBytesRead != 0) { 34 "Did not expect to reach end of file after reading 0 bytes" 35 } 36 break 37 } 38 sink.write(arrayBuffer, 0, bytesRead) 39 totalBytesRead += bytesRead 40 } 41 return totalBytesRead.toLong() 42 } 43 44 override fun close() { 45 try { 46 randomAccessFile.close() 47 } catch (ignored: Throwable) { 48 SharkLog.d(ignored) { "Failed to close file, ignoring" } 49 } 50 } 51 } 52 } 53 } 54 55