From c51b60c8e6118907ba035843fba3e0dff881b4c3 Mon Sep 17 00:00:00 2001 From: gedoor Date: Thu, 30 Dec 2021 23:24:09 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9C=AC=E5=9C=B0=E4=B9=A6=E7=B1=8D=E6=97=A0?= =?UTF-8?q?=E6=9D=83=E9=99=90=E5=88=99=E4=BF=9D=E5=AD=98=E5=88=B0=E8=87=AA?= =?UTF-8?q?=E5=B7=B1=E9=80=89=E5=AE=9A=E7=9A=84=E6=96=87=E4=BB=B6=E5=A4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../io/legado/app/model/localBook/TextFile.kt | 66 +++++++++++-------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/app/src/main/java/io/legado/app/model/localBook/TextFile.kt b/app/src/main/java/io/legado/app/model/localBook/TextFile.kt index 09caff017..4c5e4aee6 100644 --- a/app/src/main/java/io/legado/app/model/localBook/TextFile.kt +++ b/app/src/main/java/io/legado/app/model/localBook/TextFile.kt @@ -1,6 +1,8 @@ package io.legado.app.model.localBook import android.net.Uri +import android.system.Os +import android.system.OsConstants.SEEK_SET import io.legado.app.data.appDb import io.legado.app.data.entities.Book import io.legado.app.data.entities.BookChapter @@ -12,9 +14,9 @@ import io.legado.app.utils.StringUtils import io.legado.app.utils.isContentScheme import splitties.init.appCtx import java.io.File +import java.io.FileDescriptor import java.io.FileInputStream import java.io.FileNotFoundException -import java.io.InputStream import java.nio.charset.Charset import java.util.regex.Matcher import java.util.regex.Pattern @@ -26,26 +28,30 @@ class TextFile(private val book: Book) { @Throws(FileNotFoundException::class) fun getChapterList(): ArrayList { - return getBookInputStream(book).use { - val buffer = ByteArray(BUFFER_SIZE) - it.read(buffer) - if (book.charset == null) { - book.charset = EncodingDetect.getEncode(buffer) - } - charset = book.fileCharset() - val rulePattern = if (book.tocUrl.isNotEmpty()) { - Pattern.compile(book.tocUrl, Pattern.MULTILINE) - } else { - tocRules.addAll(getTocRules()) - null + return getBookFD(book).let { fd -> + try { + val buffer = ByteArray(BUFFER_SIZE) + Os.read(fd, buffer, 0, BUFFER_SIZE) + if (book.charset == null) { + book.charset = EncodingDetect.getEncode(buffer) + } + charset = book.fileCharset() + val rulePattern = if (book.tocUrl.isNotEmpty()) { + Pattern.compile(book.tocUrl, Pattern.MULTILINE) + } else { + tocRules.addAll(getTocRules()) + null + } + analyze(fd, book, rulePattern) + } finally { + Os.close(fd) } - analyze(it, book, rulePattern) } } @Throws(FileNotFoundException::class) private fun analyze( - bookIs: InputStream, + bookFd: FileDescriptor, book: Book, pattern: Pattern? ): ArrayList { @@ -53,8 +59,8 @@ class TextFile(private val book: Book) { var tocRule: TxtTocRule? = null val buffer = ByteArray(BUFFER_SIZE) val rulePattern = pattern ?: let { - bookIs.skip(0) - val length = bookIs.read(buffer) + Os.lseek(bookFd, 0, SEEK_SET) + val length = Os.read(bookFd, buffer, 0, BUFFER_SIZE) val content = String(buffer, 0, length, charset) tocRule = getTocRule(content) tocRule?.let { @@ -63,7 +69,7 @@ class TextFile(private val book: Book) { } //加载章节 //获取到的块起始点,在文件中的位置 - bookIs.skip(0) + Os.lseek(bookFd, 0, SEEK_SET) var curOffset: Long = 0 //block的个数 var blockPos = 0 @@ -72,7 +78,7 @@ class TextFile(private val book: Book) { var allLength = 0 //获取文件中的数据到buffer,直到没有数据为止 - while (bookIs.read(buffer).also { length = it } > 0) { + while (Os.read(bookFd, buffer, 0, BUFFER_SIZE).also { length = it } > 0) { blockPos++ //如果存在Chapter if (rulePattern != null) { @@ -83,7 +89,7 @@ class TextFile(private val book: Book) { blockContent = blockContent.substring(0, lastN) length = blockContent.toByteArray(charset).size allLength += length - bookIs.skip(allLength.toLong()) + Os.lseek(bookFd, allLength.toLong(), SEEK_SET) } //当前Block下使过的String的指针 var seekPos = 0 @@ -99,7 +105,7 @@ class TextFile(private val book: Book) { if (curOffset + chapterLength - lastStart > 50000 && pattern == null) { //移除不匹配的规则 tocRules.remove(tocRule) - return analyze(bookIs, book, null) + return analyze(bookFd, book, null) } //如果 seekPos == 0 && nextChapterPos != 0 表示当前block处前面有一段内容 //第一种情况一定是序章 第二种情况是上一个章节的内容 @@ -155,7 +161,7 @@ class TextFile(private val book: Book) { if (seekPos == 0 && length > 50000 && pattern == null) { //移除不匹配的规则 tocRules.remove(tocRule) - return analyze(bookIs, book, null) + return analyze(bookFd, book, null) } } else { //进行本地虚拟分章 //章节在buffer的偏移量 @@ -261,9 +267,13 @@ class TextFile(private val book: Book) { fun getContent(book: Book, bookChapter: BookChapter): String { val count = (bookChapter.end!! - bookChapter.start!!).toInt() val content = ByteArray(count) - getBookInputStream(book).use { - it.skip(bookChapter.start!!) - it.read(content) + getBookFD(book).let { fd -> + try { + Os.lseek(fd, bookChapter.start!!, SEEK_SET) + Os.read(fd, content, 0, count) + } finally { + Os.close(fd) + } } return String(content, book.fileCharset()) .substringAfter(bookChapter.title) @@ -271,12 +281,12 @@ class TextFile(private val book: Book) { } @Throws(FileNotFoundException::class) - private fun getBookInputStream(book: Book): InputStream { + private fun getBookFD(book: Book): FileDescriptor { if (book.bookUrl.isContentScheme()) { val uri = Uri.parse(book.bookUrl) - return appCtx.contentResolver.openInputStream(uri)!! + return appCtx.contentResolver.openFileDescriptor(uri, "r")!!.fileDescriptor } - return FileInputStream(File(book.bookUrl)) + return FileInputStream(File(book.bookUrl)).fd } private fun getTocRules(): List {