本地书籍无权限则保存到自己选定的文件夹

pull/1486/head
gedoor 3 years ago
parent 5434759d20
commit c51b60c8e6
  1. 46
      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,9 +28,10 @@ class TextFile(private val book: Book) {
@Throws(FileNotFoundException::class)
fun getChapterList(): ArrayList<BookChapter> {
return getBookInputStream(book).use {
return getBookFD(book).let { fd ->
try {
val buffer = ByteArray(BUFFER_SIZE)
it.read(buffer)
Os.read(fd, buffer, 0, BUFFER_SIZE)
if (book.charset == null) {
book.charset = EncodingDetect.getEncode(buffer)
}
@ -39,13 +42,16 @@ class TextFile(private val book: Book) {
tocRules.addAll(getTocRules())
null
}
analyze(it, book, rulePattern)
analyze(fd, book, rulePattern)
} finally {
Os.close(fd)
}
}
}
@Throws(FileNotFoundException::class)
private fun analyze(
bookIs: InputStream,
bookFd: FileDescriptor,
book: Book,
pattern: Pattern?
): ArrayList<BookChapter> {
@ -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<TxtTocRule> {

Loading…
Cancel
Save