diff --git a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt index 4409cf46f..69c3cb9ff 100644 --- a/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt +++ b/app/src/main/java/io/legado/app/model/localBook/LocalBook.kt @@ -109,14 +109,11 @@ object LocalBook { throw TocEmptyException(appCtx.getString(R.string.chapter_list_empty)) } val list = ArrayList(LinkedHashSet(chapters)) - var wordCount = 0 list.forEachIndexed { index, bookChapter -> bookChapter.index = index - wordCount += bookChapter.tag?.toInt() ?: 0 } book.latestChapterTitle = list.last().title book.totalChapterNum = list.size - book.wordCount = wordCount.toString() + "字" book.save() return list } 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 24cdf9f3e..78d540dca 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 @@ -90,7 +90,8 @@ class TextFile(private var book: Book) { } } } - val toc = analyze(book.tocUrl.toPattern(Pattern.MULTILINE)) + val (toc, wordCount) = analyze(book.tocUrl.toPattern(Pattern.MULTILINE)) + book.wordCount = StringUtils.wordCountFormat(wordCount) toc.forEachIndexed { index, bookChapter -> bookChapter.index = index bookChapter.bookUrl = book.bookUrl @@ -140,18 +141,19 @@ class TextFile(private var book: Book) { /** * 按规则解析目录 */ - private fun analyze(pattern: Pattern?): ArrayList { + private fun analyze(pattern: Pattern?): Pair, Int> { if (pattern?.pattern().isNullOrEmpty()) { return analyze() } - pattern ?: return analyze() val toc = arrayListOf() + var bookWordCount = 0 LocalBook.getBookInputStream(book).use { bis -> var blockContent: String //加载章节 var curOffset: Long = 0 //读取的长度 var length: Int + var lastChapterWordCount = 0 val buffer = ByteArray(bufferSize) var bufferStart = 3 bis.read(buffer, 0, 3) @@ -192,11 +194,12 @@ class TextFile(private var book: Book) { if (book.getSplitLongChapter() && curOffset + chapterLength - lastStart > maxLengthWithToc) { toc.lastOrNull()?.let { it.end = it.start + it.tag = null } //章节字数太多进行拆分 val lastTitle = toc.lastOrNull()?.title val lastTitleLength = lastTitle?.toByteArray(charset)?.size ?: 0 - val chapters = analyze( + val (chapters, wordCount) = analyze( lastStart + lastTitleLength, curOffset + chapterLength ) lastTitle?.let { @@ -205,6 +208,7 @@ class TextFile(private var book: Book) { } } toc.addAll(chapters) + bookWordCount += wordCount //创建当前章节 val curChapter = BookChapter() curChapter.title = matcher.group() @@ -222,7 +226,7 @@ class TextFile(private var book: Book) { qyChapter.title = "前言" qyChapter.start = curOffset qyChapter.end = curOffset + chapterLength - qyChapter.tag = chapterContent.length.toString() + qyChapter.tag = StringUtils.wordCountFormat(chapterContent.length) toc.add(qyChapter) book.intro = if (chapterContent.length <= 500) { chapterContent @@ -242,13 +246,16 @@ class TextFile(private var book: Book) { chapterContent.substringAfter(lastChapter.title).isBlank() //将当前段落添加上一章去 lastChapter.end = lastChapter.end!! + chapterLength - lastChapter.tag = ((lastChapter.tag?.toInt() ?: 0) + chapterContent.length).toString() + lastChapterWordCount += chapterContent.length + lastChapter.tag = StringUtils.wordCountFormat(lastChapterWordCount) //创建当前章节 val curChapter = BookChapter() curChapter.title = matcher.group() curChapter.start = lastChapter.end toc.add(curChapter) } + bookWordCount += chapterContent.length + lastChapterWordCount = 0 } else { if (toc.isNotEmpty()) { //获取章节内容 //获取上一章节 @@ -257,7 +264,7 @@ class TextFile(private var book: Book) { chapterContent.substringAfter(lastChapter.title).isBlank() lastChapter.end = lastChapter.start!! + chapterLength - lastChapter.tag = chapterContent.length.toString() + lastChapter.tag = StringUtils.wordCountFormat(chapterContent.length) //创建当前章节 val curChapter = BookChapter() curChapter.title = matcher.group() @@ -268,19 +275,24 @@ class TextFile(private var book: Book) { curChapter.title = matcher.group() curChapter.start = curOffset curChapter.end = curOffset - curChapter.tag = chapterContent.length.toString() + curChapter.tag = StringUtils.wordCountFormat(chapterContent.length) toc.add(curChapter) } + bookWordCount += chapterContent.length + lastChapterWordCount = 0 } //设置指针偏移 seekPos += chapterContent.length } + val wordCount = blockContent.length - seekPos + bookWordCount += wordCount + lastChapterWordCount += wordCount //block的偏移点 curOffset += length.toLong() //设置上一章的结尾 toc.lastOrNull()?.let { it.end = curOffset - it.tag = blockContent.substring(seekPos).length.toString() + it.tag = StringUtils.wordCountFormat(lastChapterWordCount) } } toc.lastOrNull()?.let { chapter -> @@ -288,9 +300,10 @@ class TextFile(private var book: Book) { if (book.getSplitLongChapter() && chapter.end!! - chapter.start!! > maxLengthWithToc) { val end = chapter.end!! chapter.end = chapter.start + chapter.tag = null val lastTitle = chapter.title val lastTitleLength = lastTitle.toByteArray(charset).size - val chapters = analyze( + val (chapters, _) = analyze( chapter.start!! + lastTitleLength, end ) chapters.forEachIndexed { index, bookChapter -> @@ -302,7 +315,7 @@ class TextFile(private var book: Book) { } System.gc() System.runFinalization() - return toc + return toc to bookWordCount } /** @@ -310,8 +323,9 @@ class TextFile(private var book: Book) { */ private fun analyze( fileStart: Long = 0L, fileEnd: Long = Long.MAX_VALUE - ): ArrayList { + ): Pair, Int> { val toc = arrayListOf() + var bookWordCount = 0 LocalBook.getBookInputStream(book).use { bis -> //block的个数 var blockPos = 0 @@ -320,6 +334,7 @@ class TextFile(private var book: Book) { var chapterPos = 0 //读取的长度 var length = 0 + var lastChapterWordCount = 0 val buffer = ByteArray(bufferSize) var bufferStart = 3 if (fileStart == 0L) { @@ -360,10 +375,14 @@ class TextFile(private var book: Book) { break } } + val content = String(buffer, chapterOffset, end - chapterOffset, charset) + bookWordCount += content.length + lastChapterWordCount = content.length val chapter = BookChapter() chapter.title = "第${blockPos}章($chapterPos)" chapter.start = toc.lastOrNull()?.end ?: curOffset chapter.end = chapter.start!! + end - chapterOffset + chapter.tag = StringUtils.wordCountFormat(content.length) toc.add(chapter) //减去已经被分配的长度 strLength -= (end - chapterOffset) @@ -380,19 +399,24 @@ class TextFile(private var book: Book) { curOffset += length.toLong() } //设置结尾章节 + val content = String(buffer, 0, bufferStart, charset) + bookWordCount += content.length if (bufferStart > 100 || toc.isEmpty()) { val chapter = BookChapter() chapter.title = "第${blockPos}章(${chapterPos})" chapter.start = toc.lastOrNull()?.end ?: curOffset chapter.end = chapter.start!! + bufferStart + chapter.tag = StringUtils.wordCountFormat(content.length) toc.add(chapter) } else { + val wordCount = lastChapterWordCount + content.length toc.lastOrNull()?.let { it.end = it.end!! + bufferStart + it.tag = StringUtils.wordCountFormat(wordCount) } } } - return toc + return toc to bookWordCount } /** diff --git a/app/src/main/java/io/legado/app/utils/StringUtils.kt b/app/src/main/java/io/legado/app/utils/StringUtils.kt index de0e995f8..acc118d12 100644 --- a/app/src/main/java/io/legado/app/utils/StringUtils.kt +++ b/app/src/main/java/io/legado/app/utils/StringUtils.kt @@ -8,7 +8,8 @@ import java.io.ByteArrayOutputStream import java.io.IOException import java.text.DecimalFormat import java.text.SimpleDateFormat -import java.util.* +import java.util.Calendar +import java.util.Locale import java.util.regex.Matcher import java.util.regex.Pattern import java.util.zip.GZIPInputStream @@ -22,6 +23,9 @@ object StringUtils { private const val DAY_OF_YESTERDAY = 2 private const val TIME_UNIT = 60 private val ChnMap = chnMap + private val wordCountFormatter by lazy { + DecimalFormat("#.#") + } private val chnMap: HashMap get() { @@ -232,16 +236,30 @@ object StringUtils { return isNum.matches() } + fun wordCountFormat(words: Int): String { + var wordsS = "" + if (words > 0) { + if (words > 10000) { + val df = wordCountFormatter + wordsS = df.format(words * 1.0f / 10000f.toDouble()) + "万字" + } else { + wordsS = words.toString() + "字" + } + } + return wordsS + } + fun wordCountFormat(wc: String?): String { if (wc == null) return "" var wordsS = "" if (isNumeric(wc)) { val words: Int = wc.toInt() if (words > 0) { - wordsS = words.toString() + "字" if (words > 10000) { - val df = DecimalFormat("#.#") + val df = wordCountFormatter wordsS = df.format(words * 1.0f / 10000f.toDouble()) + "万字" + } else { + wordsS = words.toString() + "字" } } } else {