diff --git a/app/src/main/java/io/legado/app/help/BookHelp.kt b/app/src/main/java/io/legado/app/help/BookHelp.kt index ee8dd0120..febe400c2 100644 --- a/app/src/main/java/io/legado/app/help/BookHelp.kt +++ b/app/src/main/java/io/legado/app/help/BookHelp.kt @@ -21,9 +21,9 @@ import kotlin.math.max import kotlin.math.min object BookHelp { - private const val cacheFolderName = "book_cache" + const val cacheFolderName = "book_cache" private const val cacheImageFolderName = "images" - private val downloadDir: File = appCtx.externalFilesDir + val downloadDir: File = appCtx.externalFilesDir private val downloadImages = CopyOnWriteArraySet() fun clearCache() { diff --git a/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt b/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt index d076187f3..1ef4702e7 100644 --- a/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt +++ b/app/src/main/java/io/legado/app/model/localBook/EpubFile.kt @@ -6,12 +6,10 @@ import android.net.Uri import android.text.TextUtils import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter +import io.legado.app.help.BookHelp import io.legado.app.utils.* import me.ag2s.epublib.domain.EpubBook -import me.ag2s.epublib.domain.MediaTypes -import me.ag2s.epublib.domain.Resources import me.ag2s.epublib.epub.EpubReader -import me.ag2s.epublib.util.ResourceUtil import org.jsoup.Jsoup import splitties.init.appCtx import java.io.File @@ -20,8 +18,7 @@ import java.io.IOException import java.io.InputStream import java.nio.charset.Charset import java.util.* -import java.util.zip.ZipEntry -import java.util.zip.ZipInputStream +import java.util.zip.ZipFile class EpubFile(var book: Book) { @@ -101,32 +98,46 @@ class EpubFile(var book: Book) { /*重写epub文件解析代码,直接读出压缩包文件生成Resources给epublib,这样的好处是可以逐一修改某些文件的格式错误*/ private fun readEpub(): EpubBook? { try { - val input = if (book.bookUrl.isContentScheme()) { - val uri = Uri.parse(book.bookUrl) - appCtx.contentResolver.openInputStream(uri) - } else { - File(book.bookUrl).inputStream() - } - input ?: return null - val inZip = ZipInputStream(input) - var zipEntry: ZipEntry? - val resources = Resources() - do { - zipEntry = inZip.nextEntry - if ((zipEntry == null) || zipEntry.isDirectory || zipEntry == ZipEntry("")) continue - val resource = ResourceUtil.createResource(zipEntry, inZip) - if (resource.mediaType == MediaTypes.XHTML) resource.inputEncoding = "UTF-8" - if (zipEntry.name.endsWith(".opf")) { - /*掌上书苑有很多自制书OPF的nameSpace格式不标准,强制修复成正确的格式*/ - val newS = String(resource.data).replace( - "\\smlns=\"http://www.idpf.org/2007/opf\"".toRegex(), - " xmlns=\"http://www.idpf.org/2007/opf\"" - ) - resource.data = newS.toByteArray() + //f + val file = FileUtils.getFile( + BookHelp.downloadDir, + BookHelp.cacheFolderName, + book.getFolderName(), + "index.epubx" + ) + if (!file.exists()) { + val input = if (book.bookUrl.isContentScheme()) { + val uri = Uri.parse(book.bookUrl) + appCtx.contentResolver.openInputStream(uri) + } else { + File(book.bookUrl).inputStream() } - resources.add(resource) - } while (zipEntry != null) - if (resources.size() > 0) return EpubReader().readEpub(resources) + input ?: return null + FileUtils.writeInputStream(file, input) + + } + return EpubReader().readEpubLazy(ZipFile(file),"utf-8") + + +// val inZip = ZipInputStream(input) +// var zipEntry: ZipEntry? +// val resources = Resources() +// do { +// zipEntry = inZip.nextEntry +// if ((zipEntry == null) || zipEntry.isDirectory || zipEntry == ZipEntry("")) continue +// val resource = ResourceUtil.createResource(zipEntry, inZip) +// if (resource.mediaType == MediaTypes.XHTML) resource.inputEncoding = "UTF-8" +// if (zipEntry.name.endsWith(".opf")) { +// /*掌上书苑有很多自制书OPF的nameSpace格式不标准,强制修复成正确的格式*/ +// val newS = String(resource.data).replace( +// "\\smlns=\"http://www.idpf.org/2007/opf\"".toRegex(), +// " xmlns=\"http://www.idpf.org/2007/opf\"" +// ) +// resource.data = newS.toByteArray() +// } +// resources.add(resource) +// } while (zipEntry != null) +// if (resources.size() > 0) return EpubReader().readEpub(resources) } catch (e: Exception) { e.printStackTrace() } diff --git a/app/src/main/java/io/legado/app/ui/book/read/page/provider/ImageProvider.kt b/app/src/main/java/io/legado/app/ui/book/read/page/provider/ImageProvider.kt index 88bea027c..0bed03ea1 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/page/provider/ImageProvider.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/page/provider/ImageProvider.kt @@ -54,7 +54,9 @@ object ImageProvider { ChapterProvider.visibleWidth, ChapterProvider.visibleHeight ) - setCache(chapterIndex, src, bitmap) + if (bitmap != null) { + setCache(chapterIndex, src, bitmap) + } bitmap } catch (e: Exception) { null diff --git a/app/src/main/java/io/legado/app/utils/BitmapUtils.kt b/app/src/main/java/io/legado/app/utils/BitmapUtils.kt index ddd29063e..39d1e1534 100644 --- a/app/src/main/java/io/legado/app/utils/BitmapUtils.kt +++ b/app/src/main/java/io/legado/app/utils/BitmapUtils.kt @@ -9,6 +9,7 @@ import android.renderscript.RenderScript import android.renderscript.ScriptIntrinsicBlur import android.view.View import splitties.init.appCtx +import java.io.FileInputStream import java.io.IOException import kotlin.math.* @@ -25,11 +26,12 @@ object BitmapUtils { * @param height 想要显示的图片的高度 * @return */ - fun decodeBitmap(path: String, width: Int, height: Int): Bitmap { + fun decodeBitmap(path: String, width: Int, height: Int): Bitmap? { val op = BitmapFactory.Options() + var ips=FileInputStream(path) // inJustDecodeBounds如果设置为true,仅仅返回图片实际的宽和高,宽和高是赋值给opts.outWidth,opts.outHeight; op.inJustDecodeBounds = true - BitmapFactory.decodeFile(path, op) //获取尺寸信息 + BitmapFactory.decodeStream(ips,null,op)//获取尺寸信息 //获取比例大小 val wRatio = ceil((op.outWidth / width).toDouble()).toInt() val hRatio = ceil((op.outHeight / height).toDouble()).toInt() @@ -41,22 +43,24 @@ object BitmapUtils { op.inSampleSize = hRatio } } + ips=FileInputStream(path) op.inJustDecodeBounds = false - return BitmapFactory.decodeFile(path, op) + return BitmapFactory.decodeStream(ips,null,op) } /** 从path中获取Bitmap图片 * @param path 图片路径 * @return */ - fun decodeBitmap(path: String): Bitmap { + fun decodeBitmap(path: String): Bitmap? { val opts = BitmapFactory.Options() + var ips=FileInputStream(path) opts.inJustDecodeBounds = true - BitmapFactory.decodeFile(path, opts) + BitmapFactory.decodeStream(ips,null,opts) opts.inSampleSize = computeSampleSize(opts, -1, 128 * 128) opts.inJustDecodeBounds = false - - return BitmapFactory.decodeFile(path, opts) + ips=FileInputStream(path) + return BitmapFactory.decodeStream(ips,null,opts) } /** diff --git a/app/src/main/java/io/legado/app/utils/FileUtils.kt b/app/src/main/java/io/legado/app/utils/FileUtils.kt index 40ef4e2b1..1e8c8b502 100644 --- a/app/src/main/java/io/legado/app/utils/FileUtils.kt +++ b/app/src/main/java/io/legado/app/utils/FileUtils.kt @@ -517,6 +517,44 @@ object FileUtils { closeSilently(fos) } } + /** + * 保存文件内容 + */ + fun writeInputStream(filepath: String, data: InputStream): Boolean { + val file = File(filepath) + return writeInputStream(file,data) + } + + /** + * 保存文件内容 + */ + fun writeInputStream(file: File, data: InputStream): Boolean { + var fos: FileOutputStream? = null + return try { + if (!file.exists()) { + file.parentFile?.mkdirs() + file.createNewFile() + } + val buffer=ByteArray(1024*4) + fos = FileOutputStream(file) + while (true) { + val len = data.read(buffer, 0, buffer.size) + if (len == -1) { + break + } else { + fos.write(buffer, 0, len) + } + } + data.close() + fos.flush() + + true + } catch (e: IOException) { + false + } finally { + closeSilently(fos) + } + } /** * 追加文本内容