【问题标题】:android, when read the file from res/raw, context.getAssets().open(fileName), the content read in are corruptedandroid, 从 res/raw, context.getAssets().open(fileName) 读取文件时,读入的内容已损坏
【发布时间】:2020-06-02 17:40:27
【问题描述】:

在 Android 上,使用 com.google.gson:gson:2.8.5,

当传递一个 josnString 并且 json 很大时(例如当字符串长度为 669304 时注意到),它得到了

com.google.gson.JsonSyntaxException: com.google.gson.stream.MalformedJsonException: 
Unterminated string at line 2902 column 564904 path $.items.result[10].quoted_status.full_text

或其他错误:

json 有子 json 字符串数组,结构类似,

{
      "items": {
        "result": [
          {subJsonString...},
          {subJsonString...},
          ...
        ]
     }
}

json字符串存储在res/raw/jsonstring.txt中,运行时读入,然后交给Gson进行反序列化。

如果减少数组中的子 json 元素(即数组中的 10 项或更少),它可以正常工作,并且单个 json 元素字符串都可以正常工作。但是当数组有更多项目时,它开始抛出。

更新: 从 res/raw 读取 json 字符串似乎是个问题 进一步看后, 当有更多项目时,日志显示从 res/raw/jsonString.txt 读取的输出 json 字符串已损坏。这里将第 11 个子项添加到 json 字符串数组后,在某个点显示 000000000...(遇到问题的第 11 项只是第 1 项的副本,所以字符串应该没问题)

这里是如何读取原始字符串以及如何记录它的代码

val jsonStr = getJsonFromFile(context, "res/raw/jsoninraw.txt")
returnedModel = gson.fromJson<T>(jsonStr, dataClassType)

......

fun getJsonFromFile(context: Context?, fileName: String): String? {
        val json: String
        try {
            val inputStream: InputStream = context.getAssets().open(fileName)
            val size = inputStream.available()
            val buffer = ByteArray(size)
            inputStream.use { it.read(buffer) }
            json = String(buffer)
        } catch (ioException: IOException) {
            ioException.printStackTrace()
            return null
        }
        return json
            .also {
                logString(it)
            }
    }

fun logString(jsonStr: String) {
    val chunkSize = 512
    var i = 0
    while (i < jsonStr.length) {
        Log.e("+++", jsonStr.substring(i, Math.min(jsonStr.length, i + chunkSize)))
        i += chunkSize
    }
}

将json字符串反序列化为模型的更好方法是什么?

【问题讨论】:

  • 似乎异常即将到来,因为您收到的 json 中有语法错误,而不是因为它的大小。尝试复制它并验证它有很多json在线实用程序
  • 试过只放入sub json(块{}包含错误行),整个json数组中的单个sun json元素工作正常,实际上在size不太大的情况下,放入三个sub那个外部 json 数组中的 json 仍然可以。
  • 很难告诉你 json 到底哪里出了问题(尤其是当你有这么大的 json 时)。如果我是你,我将格式化 json(有很多在线工具)并转到第 2902 行,我想你可能忘了放一个 ,或某种右括号。
  • 尝试使用验证工具格式化 json,并开始在 json 数组中仅放置一个 json 元素(有效),然后复制/粘贴与数组中第二个相同的 json 元素,然后是第三个, ...它适用于 10 项(将相同的一项粘贴 10 次到 json 数组中,大小为 99853)。之后再粘贴一个到数组中(现在 json 数组中现在有 11 个项目),它得到错误:gson.JsonSyntaxException: EOFException: End of input at line 2619 column 16584 path $.items.result[10].quoted_status.entities.media[0].sizes.medium.w(现在总字符串长度为 115505)。所以我觉得它与字符串长度有关。
  • 尝试在线验证json

标签: android android-resources android-assets android-resource-file


【解决方案1】:

发现 ByteArray 有 64k 限制的问题,所以超出的任何内容都已损坏。

更新后的 getJsonFromFile() 工作。

fun getJsonFromFile(context: Context?, fileName: String?): String? {
        val returnString = StringBuilder()
        var inputStream: InputStream? = null
        var isr: InputStreamReader? = null
        var input: BufferedReader? = null
        try {

            inputStream = if (context == null) {
                val cLoader = this.javaClass.classLoader
                cLoader.getResourceAsStream(fileName)
            } else {
                context.getAssets().open(fileName)
            }

          // either #1: 
          // returnString.append(inputStream?.readBytes()?.toString(Charsets.UTF_8))


         // or #2:            
            inputStream?.let {
                val inputString = inputStream.bufferedReader().use { it.readText() }
                returnString.append(inputString)
            }

// or #3:
//            isr = InputStreamReader(inputStream)
//            input = BufferedReader(isr)
//            var line: String? = ""
//            while (input.readLine().also { line = it } != null) {
//                returnString.append(line)
//            }
        } catch (e: Exception) {
            e.printStackTrace()
            return null
        } finally {
            try {
                isr?.close()
                inputStream?.close()
                input?.close()
            } catch (e2: Exception) {
                e2.message
            }
        }
        return returnString.toString()
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-14
    • 1970-01-01
    相关资源
    最近更新 更多