From 8df1cb8ab68e06762d7db9da7df430f09a4afb20 Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Fri, 24 Nov 2023 19:14:52 +0800 Subject: [PATCH 1/6] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/io/legado/app/help/CrashHandler.kt | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/io/legado/app/help/CrashHandler.kt b/app/src/main/java/io/legado/app/help/CrashHandler.kt index 2037ff2a8..c20390582 100644 --- a/app/src/main/java/io/legado/app/help/CrashHandler.kt +++ b/app/src/main/java/io/legado/app/help/CrashHandler.kt @@ -4,8 +4,10 @@ import android.annotation.SuppressLint import android.content.Context import android.net.Uri import android.os.Build +import android.os.Looper import android.webkit.WebSettings import io.legado.app.constant.AppConst +import io.legado.app.constant.AppLog import io.legado.app.exception.NoStackTraceException import io.legado.app.help.config.AppConfig import io.legado.app.help.config.LocalConfig @@ -37,9 +39,26 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler { * uncaughtException 回调函数 */ override fun uncaughtException(thread: Thread, ex: Throwable) { - ReadAloud.stop(context) - handleException(ex) - mDefaultHandler?.uncaughtException(thread, ex) + if (shouldAbsorb(ex)) { + AppLog.put("发生未捕获的异常\n${ex.localizedMessage}", ex) + Looper.loop() + } else { + ReadAloud.stop(context) + handleException(ex) + mDefaultHandler?.uncaughtException(thread, ex) + } + } + + private fun shouldAbsorb(e: Throwable): Boolean { + return when { + e::class.simpleName == "CannotDeliverBroadcastException" -> true + e is SecurityException && e.message?.contains( + "nor current process has android.permission.OBSERVE_GRANT_REVOKE_PERMISSIONS", + true + ) == true -> true + + else -> false + } } /** @@ -107,7 +126,8 @@ class CrashHandler(val context: Context) : Thread.UncaughtExceptionHandler { val time = format.format(Date()) val fileName = "crash-$time-$timestamp.log" try { - val backupPath = AppConfig.backupPath ?: throw NoStackTraceException("备份路径未配置") + val backupPath = AppConfig.backupPath + ?: throw NoStackTraceException("备份路径未配置") val uri = Uri.parse(backupPath) val fileDoc = FileDoc.fromUri(uri, true) fileDoc.createFileIfNotExist(fileName, "crash") From 53aeac8d51f5af13dc6393dd6f43fb3b64b11c8d Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Mon, 27 Nov 2023 21:58:52 +0800 Subject: [PATCH 2/6] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/book/read/config/BgTextConfigDialog.kt | 36 ++++++++++++------- .../io/legado/app/utils/FileDocExtensions.kt | 8 ++--- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt index b86675476..2f16f4628 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/BgTextConfigDialog.kt @@ -249,10 +249,11 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) { val fontPath = ReadBookConfig.textFont if (fontPath.isNotEmpty()) { val fontName = FileUtils.getName(fontPath) - val fontBytes = fontPath.parseToUri().readBytes(requireContext()) - fontBytes.let { + val fontInputStream = + fontPath.parseToUri().inputStream(requireContext()).getOrNull() + fontInputStream?.use { val fontExportFile = FileUtils.createFileIfNotExist(configDir, fontName) - fontExportFile.writeBytes(it) + it.copyTo(fontExportFile.outputStream()) exportFiles.add(fontExportFile) } } @@ -261,8 +262,10 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) { val bgFile = File(ReadBookConfig.durConfig.bgStr) if (bgFile.exists()) { val bgExportFile = File(FileUtils.getPath(configDir, bgName)) - bgFile.copyTo(bgExportFile) - exportFiles.add(bgExportFile) + if (!bgExportFile.exists()) { + bgFile.copyTo(bgExportFile) + exportFiles.add(bgExportFile) + } } } if (ReadBookConfig.durConfig.bgTypeNight == 2) { @@ -270,8 +273,10 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) { val bgFile = File(ReadBookConfig.durConfig.bgStrNight) if (bgFile.exists()) { val bgExportFile = File(FileUtils.getPath(configDir, bgName)) - bgFile.copyTo(bgExportFile) - exportFiles.add(bgExportFile) + if (!bgExportFile.exists()) { + bgFile.copyTo(bgExportFile) + exportFiles.add(bgExportFile) + } } } if (ReadBookConfig.durConfig.bgTypeEInk == 2) { @@ -279,8 +284,10 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) { val bgFile = File(ReadBookConfig.durConfig.bgStrEInk) if (bgFile.exists()) { val bgExportFile = File(FileUtils.getPath(configDir, bgName)) - bgFile.copyTo(bgExportFile) - exportFiles.add(bgExportFile) + if (!bgExportFile.exists()) { + bgFile.copyTo(bgExportFile) + exportFiles.add(bgExportFile) + } } } val configZipPath = FileUtils.getPath(requireContext().externalCache, configFileName) @@ -288,14 +295,17 @@ class BgTextConfigDialog : BaseDialogFragment(R.layout.dialog_read_bg_text) { if (uri.isContentScheme()) { DocumentFile.fromTreeUri(requireContext(), uri)?.let { treeDoc -> treeDoc.findFile(exportFileName)?.delete() - treeDoc.createFile("", exportFileName) - ?.writeBytes(requireContext(), File(configZipPath).readBytes()) + val out = treeDoc.createFile("", exportFileName)?.openOutputStream() + out?.use { + File(configZipPath).inputStream().use { + it.copyTo(out) + } + } } } else { val exportPath = FileUtils.getPath(File(uri.path!!), exportFileName) FileUtils.delete(exportPath) - FileUtils.createFileIfNotExist(exportPath) - .writeBytes(File(configZipPath).readBytes()) + File(configZipPath).copyTo(FileUtils.createFileIfNotExist(exportPath)) } } }.onSuccess { diff --git a/app/src/main/java/io/legado/app/utils/FileDocExtensions.kt b/app/src/main/java/io/legado/app/utils/FileDocExtensions.kt index 70a6682d0..3a5aa5f5e 100644 --- a/app/src/main/java/io/legado/app/utils/FileDocExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/FileDocExtensions.kt @@ -212,7 +212,7 @@ fun FileDoc.createFileIfNotExist( vararg subDirs: String ): FileDoc { return if (uri.isContentScheme()) { - val documentFile = DocumentFile.fromTreeUri(appCtx, uri)!! + val documentFile = asDocumentFile()!! val tmp = DocumentUtils.createFileIfNotExist(documentFile, fileName, *subDirs)!! FileDoc.fromDocumentFile(tmp) } else { @@ -226,7 +226,7 @@ fun FileDoc.createFolderIfNotExist( vararg subDirs: String ): FileDoc { return if (uri.isContentScheme()) { - val documentFile = DocumentFile.fromTreeUri(appCtx, uri)!! + val documentFile = asDocumentFile()!! val tmp = DocumentUtils.createFolderIfNotExist(documentFile, *subDirs)!! FileDoc.fromDocumentFile(tmp) } else { @@ -257,7 +257,7 @@ fun FileDoc.exists( vararg subDirs: String ): Boolean { return if (uri.isContentScheme()) { - DocumentUtils.exists(DocumentFile.fromTreeUri(appCtx, uri)!!, fileName, *subDirs) + DocumentUtils.exists(asDocumentFile()!!, fileName, *subDirs) } else { val path = FileUtils.getPath(uri.path!!, *subDirs) + File.separator + fileName FileUtils.exist(path) @@ -266,7 +266,7 @@ fun FileDoc.exists( fun FileDoc.exists(): Boolean { return if (uri.isContentScheme()) { - DocumentFile.fromTreeUri(appCtx, uri)!!.exists() + asDocumentFile()!!.exists() } else { FileUtils.exist(uri.path!!) } From 87c89b588c7f6dab73c2d3c6612d351ebf46cb62 Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Tue, 28 Nov 2023 14:38:38 +0800 Subject: [PATCH 3/6] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/io/legado/app/ui/browser/WebViewActivity.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/io/legado/app/ui/browser/WebViewActivity.kt b/app/src/main/java/io/legado/app/ui/browser/WebViewActivity.kt index 9b320dc90..57b026fb7 100644 --- a/app/src/main/java/io/legado/app/ui/browser/WebViewActivity.kt +++ b/app/src/main/java/io/legado/app/ui/browser/WebViewActivity.kt @@ -246,7 +246,7 @@ class WebViewActivity : VMBaseActivity() { } else -> { - binding.root.longSnackbar("跳转其它应用", "确认") { + binding.root.longSnackbar(R.string.jump_to_another_app, R.string.confirm) { openUrl(url) } return true From a84d6e217836c9cefaa18f00ceda42cd4210658c Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Tue, 28 Nov 2023 22:25:38 +0800 Subject: [PATCH 4/6] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/proguard-rules.pro | 4 +- app/src/main/java/io/legado/app/App.kt | 7 ++- .../legado/app/data/entities/BookChapter.kt | 1 - .../java/io/legado/app/help/JsExtensions.kt | 2 +- .../legado/app/help/book/ContentProcessor.kt | 2 +- .../ui/book/read/config/ReadStyleDialog.kt | 1 - .../searchContent/SearchContentViewModel.kt | 4 +- .../java/io/legado/app/utils/ChineseUtils.kt | 45 +++++++++++++++++++ .../io/legado/app/utils/TrieExtensions.kt | 39 ++++++++++++++++ 9 files changed, 95 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/io/legado/app/utils/ChineseUtils.kt create mode 100644 app/src/main/java/io/legado/app/utils/TrieExtensions.kt diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 5db9efc06..3104daffc 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -250,8 +250,8 @@ ## 对外提供api -keep class io.legado.app.api.ReturnData{*;} -# Apache Commons Compress --keep class org.apache.commons.compress.archivers.** {*;} +# 繁简转换 +-keep class com.github.liuyueyi.quick.transfer.** {*;} #-------------------Cronet------------------------------------ diff --git a/app/src/main/java/io/legado/app/App.kt b/app/src/main/java/io/legado/app/App.kt index 550162a56..245a57904 100644 --- a/app/src/main/java/io/legado/app/App.kt +++ b/app/src/main/java/io/legado/app/App.kt @@ -7,7 +7,6 @@ import android.content.Context import android.content.pm.ActivityInfo import android.content.res.Configuration import android.os.Build -import com.github.liuyueyi.quick.transfer.ChineseUtils import com.github.liuyueyi.quick.transfer.constants.TransType import com.jeremyliao.liveeventbus.LiveEventBus import io.legado.app.base.AppContextWrapper @@ -31,6 +30,7 @@ import io.legado.app.help.http.okHttpClient import io.legado.app.help.source.SourceHelp import io.legado.app.help.storage.Backup import io.legado.app.model.BookCover +import io.legado.app.utils.ChineseUtils import io.legado.app.utils.defaultSharedPreferences import io.legado.app.utils.getPrefBoolean import kotlinx.coroutines.launch @@ -73,7 +73,10 @@ class App : Application() { Backup.clearCache() //初始化简繁转换引擎 when (AppConfig.chineseConverterType) { - 1 -> ChineseUtils.preLoad(true, TransType.TRADITIONAL_TO_SIMPLE) + 1 -> launch { + ChineseUtils.fixT2sDict() + } + 2 -> ChineseUtils.preLoad(true, TransType.SIMPLE_TO_TRADITIONAL) } //调整排序序号 diff --git a/app/src/main/java/io/legado/app/data/entities/BookChapter.kt b/app/src/main/java/io/legado/app/data/entities/BookChapter.kt index 02169943d..705efcd84 100644 --- a/app/src/main/java/io/legado/app/data/entities/BookChapter.kt +++ b/app/src/main/java/io/legado/app/data/entities/BookChapter.kt @@ -5,7 +5,6 @@ import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.Ignore import androidx.room.Index -import com.github.liuyueyi.quick.transfer.ChineseUtils import io.legado.app.R import io.legado.app.constant.AppLog import io.legado.app.constant.AppPattern diff --git a/app/src/main/java/io/legado/app/help/JsExtensions.kt b/app/src/main/java/io/legado/app/help/JsExtensions.kt index 2ef43fd90..a464c2a96 100644 --- a/app/src/main/java/io/legado/app/help/JsExtensions.kt +++ b/app/src/main/java/io/legado/app/help/JsExtensions.kt @@ -5,7 +5,7 @@ import android.webkit.WebSettings import androidx.annotation.Keep import cn.hutool.core.codec.Base64 import cn.hutool.core.util.HexUtil -import com.github.liuyueyi.quick.transfer.ChineseUtils +import io.legado.app.utils.ChineseUtils import io.legado.app.constant.AppConst import io.legado.app.constant.AppConst.dateFormat import io.legado.app.constant.AppLog diff --git a/app/src/main/java/io/legado/app/help/book/ContentProcessor.kt b/app/src/main/java/io/legado/app/help/book/ContentProcessor.kt index 9c913d59d..e48451dc2 100644 --- a/app/src/main/java/io/legado/app/help/book/ContentProcessor.kt +++ b/app/src/main/java/io/legado/app/help/book/ContentProcessor.kt @@ -1,6 +1,5 @@ package io.legado.app.help.book -import com.github.liuyueyi.quick.transfer.ChineseUtils import io.legado.app.constant.AppLog import io.legado.app.constant.AppPattern.spaceRegex import io.legado.app.data.appDb @@ -10,6 +9,7 @@ import io.legado.app.data.entities.ReplaceRule import io.legado.app.exception.RegexTimeoutException import io.legado.app.help.config.AppConfig import io.legado.app.help.config.ReadBookConfig +import io.legado.app.utils.ChineseUtils import io.legado.app.utils.escapeRegex import io.legado.app.utils.replace import io.legado.app.utils.stackTraceStr diff --git a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt index 95bffaf46..40eecd230 100644 --- a/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt +++ b/app/src/main/java/io/legado/app/ui/book/read/config/ReadStyleDialog.kt @@ -7,7 +7,6 @@ import android.view.View import android.view.ViewGroup import android.view.WindowManager import androidx.core.view.get -import com.github.liuyueyi.quick.transfer.ChineseUtils import com.github.liuyueyi.quick.transfer.constants.TransType import io.legado.app.R import io.legado.app.base.BaseDialogFragment diff --git a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt index 3a72eb280..f5d774795 100644 --- a/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt +++ b/app/src/main/java/io/legado/app/ui/book/searchContent/SearchContentViewModel.kt @@ -2,7 +2,6 @@ package io.legado.app.ui.book.searchContent import android.app.Application -import com.github.liuyueyi.quick.transfer.ChineseUtils import io.legado.app.base.BaseViewModel import io.legado.app.data.appDb import io.legado.app.data.entities.Book @@ -10,13 +9,14 @@ import io.legado.app.data.entities.BookChapter import io.legado.app.help.book.BookHelp import io.legado.app.help.book.ContentProcessor import io.legado.app.help.config.AppConfig +import io.legado.app.utils.ChineseUtils import kotlinx.coroutines.ensureActive import kotlin.coroutines.coroutineContext class SearchContentViewModel(application: Application) : BaseViewModel(application) { var bookUrl: String = "" var book: Book? = null - var contentProcessor: ContentProcessor? = null + private var contentProcessor: ContentProcessor? = null var lastQuery: String = "" var searchResultCounts = 0 val cacheChapterNames = hashSetOf() diff --git a/app/src/main/java/io/legado/app/utils/ChineseUtils.kt b/app/src/main/java/io/legado/app/utils/ChineseUtils.kt new file mode 100644 index 000000000..7f18abecb --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/ChineseUtils.kt @@ -0,0 +1,45 @@ +package io.legado.app.utils + +import com.github.liuyueyi.quick.transfer.ChineseUtils +import com.github.liuyueyi.quick.transfer.constants.TransType +import com.github.liuyueyi.quick.transfer.dictionary.DictionaryContainer + +object ChineseUtils { + + private var fixed = false + + fun s2t(content: String): String { + return ChineseUtils.s2t(content) + } + + fun t2s(content: String): String { + if (!fixed) { + fixed = true + fixT2sDict() + } + return ChineseUtils.t2s(content) + } + + fun preLoad(async: Boolean, vararg transType: TransType) { + ChineseUtils.preLoad(async, *transType) + } + + fun unLoad(vararg transType: TransType) { + ChineseUtils.unLoad(*transType) + } + + fun fixT2sDict() { + val dict = DictionaryContainer.getInstance().getDictionary(TransType.TRADITIONAL_TO_SIMPLE) + dict.chars.run { + remove('劈') + remove('脊') + } + kotlin.runCatching { + dict.dict.run { + remove("支援") + remove("路易斯") + } + } + } + +} diff --git a/app/src/main/java/io/legado/app/utils/TrieExtensions.kt b/app/src/main/java/io/legado/app/utils/TrieExtensions.kt new file mode 100644 index 000000000..e5627e7dc --- /dev/null +++ b/app/src/main/java/io/legado/app/utils/TrieExtensions.kt @@ -0,0 +1,39 @@ +package io.legado.app.utils + +import com.github.liuyueyi.quick.transfer.Trie +import com.github.liuyueyi.quick.transfer.TrieNode +import java.util.HashMap + +fun Trie.getRoot(): TrieNode { + val rootField = javaClass.getDeclaredField("root") + .apply { isAccessible = true } + @Suppress("UNCHECKED_CAST") + return rootField.get(this) as TrieNode +} + +fun TrieNode.getChildren(): HashMap> { + val childrenField = javaClass.getDeclaredField("children") + .apply { isAccessible = true } + @Suppress("UNCHECKED_CAST") + return childrenField.get(this) as HashMap> +} + +fun Trie.remove(value: String) { + var node = getRoot() + val nodes = arrayListOf>() + val chars = value.toCharArray() + for (c in chars) { + nodes.add(node) + node = node.getChildren()[c] ?: break + if (!node.isLeaf) { + continue + } + for ((ch, n) in chars.reversed().zip(nodes.reversed())) { + val children = n.getChildren() + children.remove(ch) + if (children.isNotEmpty()) { + break + } + } + } +} From 301d70c081f5a002c9ba391190d65f7ddd3cd81f Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Wed, 29 Nov 2023 09:55:00 +0800 Subject: [PATCH 5/6] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/io/legado/app/service/ExportBookService.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/io/legado/app/service/ExportBookService.kt b/app/src/main/java/io/legado/app/service/ExportBookService.kt index 93d33e95c..04c18cbe5 100644 --- a/app/src/main/java/io/legado/app/service/ExportBookService.kt +++ b/app/src/main/java/io/legado/app/service/ExportBookService.kt @@ -140,7 +140,7 @@ class ExportBookService : BaseService() { startForeground(NotificationId.ExportBookService, notification.build()) } - private fun upExportNotification() { + private fun upExportNotification(finish: Boolean = false) { val notification = NotificationCompat.Builder(this, AppConst.channelIdDownload) .setSmallIcon(R.drawable.ic_export) .setSubText(getString(R.string.export_book)) @@ -149,7 +149,7 @@ class ExportBookService : BaseService() { .setContentText(notificationContentText) .setDeleteIntent(servicePendingIntent(IntentAction.stop)) .setGroup(groupKey) - if (exportJob?.isActive == true) { + if (!finish) { notification.setOngoing(true) notification.addAction( R.drawable.ic_stop_black_24dp, @@ -168,7 +168,7 @@ class ExportBookService : BaseService() { while (true) { val (bookUrl, exportConfig) = waitExportBooks.entries.firstOrNull() ?: let { notificationContentText = "导出完成" - upExportNotification() + upExportNotification(true) return@launch } exportProgress[bookUrl] = 0 From 6cd087be87e4ba056ce595da433987cd340701a9 Mon Sep 17 00:00:00 2001 From: Horis <821938089@qq.com> Date: Wed, 29 Nov 2023 11:19:23 +0800 Subject: [PATCH 6/6] =?UTF-8?q?=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../legado/app/service/ExportBookService.kt | 60 +++++++++++-------- .../io/legado/app/utils/FileExtensions.kt | 5 ++ 2 files changed, 39 insertions(+), 26 deletions(-) diff --git a/app/src/main/java/io/legado/app/service/ExportBookService.kt b/app/src/main/java/io/legado/app/service/ExportBookService.kt index 04c18cbe5..13f76073e 100644 --- a/app/src/main/java/io/legado/app/service/ExportBookService.kt +++ b/app/src/main/java/io/legado/app/service/ExportBookService.kt @@ -41,6 +41,7 @@ import io.legado.app.utils.activityPendingIntent import io.legado.app.utils.cnCompare import io.legado.app.utils.createFolderIfNotExist import io.legado.app.utils.isContentScheme +import io.legado.app.utils.outputStream import io.legado.app.utils.postEvent import io.legado.app.utils.readBytes import io.legado.app.utils.readText @@ -230,21 +231,24 @@ class ExportBookService : BaseService() { DocumentUtils.delete(doc, filename) val bookDoc = DocumentUtils.createFileIfNotExist(doc, filename) ?: throw NoStackTraceException("创建文档失败,请尝试重新设置导出文件夹") + val charset = Charset.forName(AppConfig.exportCharset) contentResolver.openOutputStream(bookDoc.uri, "wa")?.use { bookOs -> - getAllContents(book) { text, srcList -> - bookOs.write(text.toByteArray(Charset.forName(AppConfig.exportCharset))) - srcList?.forEach { - val vFile = BookHelp.getImage(book, it.src) - if (vFile.exists()) { - DocumentUtils.createFileIfNotExist( - doc, - "${it.index}-${MD5Utils.md5Encode16(it.src)}.jpg", - subDirs = arrayOf( - "${book.name}_${book.author}", - "images", - it.chapterTitle - ) - )?.writeBytes(this, vFile.readBytes()) + BufferedOutputStream(bookOs, 64 * 1024).use { bos -> + getAllContents(book) { text, srcList -> + bos.write(text.toByteArray(charset)) + srcList?.forEach { + val vFile = BookHelp.getImage(book, it.src) + if (vFile.exists()) { + DocumentUtils.createFileIfNotExist( + doc, + "${it.index}-${MD5Utils.md5Encode16(it.src)}.jpg", + subDirs = arrayOf( + "${book.name}_${book.author}", + "images", + it.chapterTitle + ) + )?.writeBytes(this, vFile.readBytes()) + } } } } @@ -259,18 +263,22 @@ class ExportBookService : BaseService() { val filename = book.getExportFileName("txt") val bookPath = FileUtils.getPath(file, filename) val bookFile = FileUtils.createFileWithReplace(bookPath) - getAllContents(book) { text, srcList -> - bookFile.appendText(text, Charset.forName(AppConfig.exportCharset)) - srcList?.forEach { - val vFile = BookHelp.getImage(book, it.src) - if (vFile.exists()) { - FileUtils.createFileIfNotExist( - file, - "${book.name}_${book.author}", - "images", - it.chapterTitle, - "${it.index}-${MD5Utils.md5Encode16(it.src)}.jpg" - ).writeBytes(vFile.readBytes()) + val charset = Charset.forName(AppConfig.exportCharset) + val bos = BufferedOutputStream(bookFile.outputStream(true), 64 * 1024) + bos.use { + getAllContents(book) { text, srcList -> + bos.write(text.toByteArray(charset)) + srcList?.forEach { + val vFile = BookHelp.getImage(book, it.src) + if (vFile.exists()) { + FileUtils.createFileIfNotExist( + file, + "${book.name}_${book.author}", + "images", + it.chapterTitle, + "${it.index}-${MD5Utils.md5Encode16(it.src)}.jpg" + ).writeBytes(vFile.readBytes()) + } } } } diff --git a/app/src/main/java/io/legado/app/utils/FileExtensions.kt b/app/src/main/java/io/legado/app/utils/FileExtensions.kt index fff827df8..018497276 100644 --- a/app/src/main/java/io/legado/app/utils/FileExtensions.kt +++ b/app/src/main/java/io/legado/app/utils/FileExtensions.kt @@ -4,6 +4,7 @@ package io.legado.app.utils import android.net.Uri import java.io.File +import java.io.FileOutputStream fun File.getFile(vararg subDirFiles: String): File { val path = FileUtils.getPath(this, *subDirFiles) @@ -79,3 +80,7 @@ fun File.checkWrite(): Boolean { false } } + +fun File.outputStream(append: Boolean = false): FileOutputStream { + return FileOutputStream(this, append) +}