Просмотр исходного кода

导入书源直接解析流,防止书源太大报错

kunfei 4 лет назад
Родитель
Сommit
75dc0e5268

+ 5 - 0
app/src/main/java/io/legado/app/data/entities/BookSource.kt

@@ -11,6 +11,7 @@ import io.legado.app.utils.*
 import kotlinx.parcelize.IgnoredOnParcel
 import kotlinx.parcelize.Parcelize
 import splitties.init.appCtx
+import java.io.InputStream
 
 @Parcelize
 @TypeConverters(BookSource.Converters::class)
@@ -210,6 +211,10 @@ data class BookSource(
         fun fromJsonArray(json: String): List<BookSource> {
             return SourceAnalyzer.jsonToBookSources(json)
         }
+
+        fun fromJsonArray(inputStream: InputStream): Result<MutableList<BookSource>> {
+            return SourceAnalyzer.jsonToBookSources(inputStream)
+        }
     }
 
     class Converters {

+ 25 - 4
app/src/main/java/io/legado/app/help/SourceAnalyzer.kt

@@ -8,6 +8,7 @@ import io.legado.app.constant.BookType
 import io.legado.app.data.entities.BookSource
 import io.legado.app.data.entities.rule.*
 import io.legado.app.utils.*
+import java.io.InputStream
 
 import java.util.regex.Pattern
 
@@ -18,16 +19,36 @@ object SourceAnalyzer {
 
     fun jsonToBookSources(json: String): List<BookSource> {
         val bookSources = mutableListOf<BookSource>()
-        if (json.isJsonArray()) {
-            val items: List<Map<String, Any>> = jsonPath.parse(json).read("$")
-            for (item in items) {
+        val items: List<Map<String, Any>> = jsonPath.parse(json).read("$")
+        for (item in items) {
+            val jsonItem = jsonPath.parse(item)
+            jsonToBookSource(jsonItem.jsonString())?.let {
+                bookSources.add(it)
+            }
+        }
+        return bookSources
+    }
+
+    fun jsonToBookSources(inputStream: InputStream): Result<MutableList<BookSource>> {
+        return kotlin.runCatching {
+            val bookSources = mutableListOf<BookSource>()
+            kotlin.runCatching {
+                val items: List<Map<String, Any>> = jsonPath.parse(inputStream).read("$")
+                for (item in items) {
+                    val jsonItem = jsonPath.parse(item)
+                    jsonToBookSource(jsonItem.jsonString())?.let {
+                        bookSources.add(it)
+                    }
+                }
+            }.onFailure {
+                val item: Map<String, Any> = jsonPath.parse(inputStream).read("$")
                 val jsonItem = jsonPath.parse(item)
                 jsonToBookSource(jsonItem.jsonString())?.let {
                     bookSources.add(it)
                 }
             }
+            bookSources
         }
-        return bookSources
     }
 
     fun jsonToBookSource(json: String): BookSource? {

+ 4 - 2
app/src/main/java/io/legado/app/help/storage/Restore.kt

@@ -22,6 +22,7 @@ import kotlinx.coroutines.delay
 import kotlinx.coroutines.withContext
 import splitties.init.appCtx
 import java.io.File
+import java.io.FileInputStream
 
 
 object Restore {
@@ -192,8 +193,9 @@ object Restore {
     private inline fun <reified T> fileToListT(path: String, fileName: String): List<T>? {
         try {
             val file = FileUtils.createFileIfNotExist(path + File.separator + fileName)
-            val json = file.readText()
-            return GSON.fromJsonArray<T>(json).getOrThrow()
+            FileInputStream(file).use {
+                return GSON.fromJsonArray<T>(it).getOrThrow()
+            }
         } catch (e: Exception) {
             AppLog.put("$fileName\n读取解析出错\n${e.localizedMessage}", e)
             appCtx.toastOnUi("$fileName\n读取文件出错\n${e.localizedMessage}")

+ 2 - 21
app/src/main/java/io/legado/app/ui/association/ImportBookSourceViewModel.kt

@@ -14,7 +14,6 @@ import io.legado.app.help.SourceHelp
 import io.legado.app.help.config.AppConfig
 import io.legado.app.help.http.newCallResponseBody
 import io.legado.app.help.http.okHttpClient
-import io.legado.app.help.http.text
 import io.legado.app.utils.*
 
 
@@ -123,26 +122,8 @@ class ImportBookSourceViewModel(app: Application) : BaseViewModel(app) {
     private suspend fun importSourceUrl(url: String) {
         okHttpClient.newCallResponseBody {
             url(url)
-        }.text("utf-8").let { body ->
-            when {
-                body.isJsonArray() -> {
-                    val items: List<Map<String, Any>> = jsonPath.parse(body).read("$")
-                    for (item in items) {
-                        val jsonItem = jsonPath.parse(item)
-                        BookSource.fromJson(jsonItem.jsonString())?.let { source ->
-                            allSources.add(source)
-                        }
-                    }
-                }
-                body.isJsonObject() -> {
-                    BookSource.fromJson(body)?.let {
-                        allSources.add(it)
-                    }
-                }
-                else -> {
-                    throw NoStackTraceException(context.getString(R.string.wrong_format))
-                }
-            }
+        }.byteStream().let {
+            allSources.addAll(BookSource.fromJsonArray(it).getOrThrow())
         }
     }
 

+ 16 - 0
app/src/main/java/io/legado/app/utils/GsonExtensions.kt

@@ -4,6 +4,8 @@ import com.google.gson.*
 import com.google.gson.internal.LinkedTreeMap
 import com.google.gson.reflect.TypeToken
 import com.google.gson.stream.JsonWriter
+import java.io.InputStream
+import java.io.InputStreamReader
 import java.io.OutputStream
 import java.io.OutputStreamWriter
 import java.lang.reflect.ParameterizedType
@@ -37,6 +39,20 @@ inline fun <reified T> Gson.fromJsonArray(json: String?): Result<List<T>?> {
     }
 }
 
+inline fun <reified T> Gson.fromJsonObject(inputStream: InputStream?): Result<T?> {
+    return kotlin.runCatching {
+        val reader = InputStreamReader(inputStream)
+        fromJson(reader, genericType<T>()) as? T
+    }
+}
+
+inline fun <reified T> Gson.fromJsonArray(inputStream: InputStream?): Result<List<T>?> {
+    return kotlin.runCatching {
+        val reader = InputStreamReader(inputStream)
+        fromJson(reader, ParameterizedTypeImpl(T::class.java)) as? List<T>
+    }
+}
+
 fun Gson.writeToOutputStream(out: OutputStream, any: Any) {
     val writer = JsonWriter(OutputStreamWriter(out, "UTF-8"))
     writer.setIndent("  ")