You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Android离线日英词典解析JMDict XML时触发XmlPullParserException异常求助

Android离线日英词典解析JMDict XML时触发XmlPullParserException异常求助

嘿,我看你在做Jetpack Compose离线日英词典的时候,解析JMDict XML遇到了XmlPullParserException的崩溃问题,刚好我之前折腾过类似的场景,来给你梳理下大概率的问题原因和解决办法!

先说说异常的核心原因

XmlPullParserException: Unexpected token 这种报错,在解析JMDict这类自定义实体很多的XML时,90%的概率是编码不匹配或者自定义实体未被解析器识别导致的,咱们结合你的代码和JMDict的特性来拆解:

问题1:未指定XML编码

JMDict的官方XML文件默认是UTF-8编码,但你的代码里parser.setInput(input, null)没有指定编码,解析器会尝试自动推断,一旦推断错误就会把某些字节当成非法字符,触发异常。

问题2:自定义实体未被处理

你提供的XML示例里有&n;&exp;这类标记,这些是JMDict定义的自定义实体,它们的定义都在JMdict.dtd文件里。如果你的assets目录里没有这个DTD文件,或者解析器没启用DTD处理,就会把这些实体当成非法的未知 token,直接报错。

问题3:XML文件可能不完整/损坏

如果下载的JMDict XML文件中途截断、或者下载过程中出现了数据损坏,也会导致解析器读到不合法的内容触发异常。


针对性解决步骤

1. 补全DTD文件并配置解析器

  • 先把JMdict.dtd文件下载下来(和你的JMDict XML版本匹配),放到assets目录里,和jMdict.xml同级。
  • 修改你的解析函数,启用DTD处理并指定UTF-8编码:
fun countEntriesInXml(input: InputStream): Float {
    val parser = XmlPullParserFactory.newInstance().newPullParser()
    // 启用DTD解析,让解析器能识别JMDict的自定义实体
    parser.setFeature(XmlPullParser.FEATURE_PROCESS_DOCDECL, true)
    // 明确指定UTF-8编码,避免自动推断出错
    parser.setInput(input, "UTF-8")
    
    var count = 0
    var event = parser.eventType
    while (event != XmlPullParser.END_DOCUMENT) {
        if (event == XmlPullParser.START_TAG && parser.name == "entry") {
            count++
        }
        // 正常推进解析,这里如果还是遇到异常,可以临时跳过标签(不推荐,优先解决根本问题)
        event = try {
            parser.next()
        } catch (e: XmlPullParserException) {
            parser.nextTag()
        }
    }
    return count.toFloat()
}

2. 验证XML文件完整性

检查assets里的jMdict.xml文件大小是否和官方下载的一致,也可以用电脑上的XML编辑器(比如VS Code的XML插件)打开看看,能不能正常解析,有没有报错的节点。

3. 优化资源加载(可选)

JMDict的XML文件非常大,直接在主线程解析会导致ANR甚至崩溃,建议把解析逻辑放到WorkManager或者Coroutine的IO线程里执行,避免阻塞主线程。


你可以先试试前两个核心步骤,尤其是补全DTD文件和指定编码,应该能解决当前的异常。如果还是有问题,可以在捕获异常时打印parser.position()parser.text,看看具体是哪个位置的内容触发了错误,方便进一步定位。

内容来源于stack exchange

火山引擎 最新活动