Fix RAR loading

Closes #10302
This commit is contained in:
arkon 2024-01-06 17:09:38 -05:00
parent bbd8098a61
commit 80b7d14af1

View file

@ -10,6 +10,7 @@ import java.io.File
import java.io.InputStream import java.io.InputStream
import java.io.PipedInputStream import java.io.PipedInputStream
import java.io.PipedOutputStream import java.io.PipedOutputStream
import java.util.concurrent.Executors
/** /**
* Loader used to load a chapter from a .rar or .cbr file. * Loader used to load a chapter from a .rar or .cbr file.
@ -20,13 +21,18 @@ internal class RarPageLoader(file: File) : PageLoader() {
override var isLocal: Boolean = true override var isLocal: Boolean = true
/**
* Pool for copying compressed files to an input stream.
*/
private val pool = Executors.newFixedThreadPool(1)
override suspend fun getPages(): List<ReaderPage> { override suspend fun getPages(): List<ReaderPage> {
return rar.fileHeaders.asSequence() return rar.fileHeaders.asSequence()
.filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { rar.getInputStream(it) } } .filter { !it.isDirectory && ImageUtil.isImage(it.fileName) { rar.getInputStream(it) } }
.sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) } .sortedWith { f1, f2 -> f1.fileName.compareToCaseInsensitiveNaturalOrder(f2.fileName) }
.mapIndexed { i, header -> .mapIndexed { i, header ->
ReaderPage(i).apply { ReaderPage(i).apply {
stream = { getStream(rar, header) } stream = { getStream(header) }
status = Page.State.READY status = Page.State.READY
} }
} }
@ -40,15 +46,16 @@ internal class RarPageLoader(file: File) : PageLoader() {
override fun recycle() { override fun recycle() {
super.recycle() super.recycle()
rar.close() rar.close()
pool.shutdown()
} }
/** /**
* Returns an input stream for the given [header]. * Returns an input stream for the given [header].
*/ */
private fun getStream(rar: Archive, header: FileHeader): InputStream { private fun getStream(header: FileHeader): InputStream {
val pipeIn = PipedInputStream() val pipeIn = PipedInputStream()
val pipeOut = PipedOutputStream(pipeIn) val pipeOut = PipedOutputStream(pipeIn)
synchronized(this) { pool.execute {
try { try {
pipeOut.use { pipeOut.use {
rar.extractFile(header, it) rar.extractFile(header, it)