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