IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Kotlin/Android 检测文本编码

    R0uter发表于 2024-11-02 06:54:08
    love 0

    去落格博客阅读完整排版的Kotlin/Android 检测文本编码

    最近更新:2nd 11 月, 2024

    最近在做 Android 版本的落格输入法,在导入码表的时候我犯了难。因为落格输入法的码表是支持 utf8 和 gb18030 两种编码格式的,甚至我自己内置的码表也是混用这两种格式的。在 Swift 或者 Python 中,如果你使用错误的编码去解码文本,就会收到报错。利用这个办法,我可以轻松实现两种编码的检测——先用 utf8 解码,报错了就再试试 gb18030. 简单方便,足够我用。

    可是这个情况在 Kotlin 中不灵了!在 Java 中,如果你使用错误编码解码文本,它只会给你一坨乱码!这在其他语言中通常都需要明确强制解码才能实现……但在 Java 中是默认的,而且没有办法让它报错。

    try {
                val assetName = ""
                val inputStream = context.assets.open(assetName)
                reader = InputStreamReader(inputStream, Charsets.UTF_8) // 任何编码的文本都不会触发报错
            } catch (e: IOException) {
                // means file not in the asset, so we try load it from the file system
            } catch (e: Exception) {
                return importFalse(context, "码表编码格式错误,请确定编码为 uft-8 不要有 BOM!")
            }

    这就很难办了,经过查询,我找到了一个号称能检测各种编码的第三方库:https://github.com/albfernandez/juniversalchardet 但很遗憾,它并不能成功检测 gb18030.

     

    最后,中文的问题果然还得用中文来搜索,http://www.meilongkui.com/archives/473 我找到了这么一篇文章,据说文中的调用方法是可以触发报错的。我按文中的方案先读取一小段内容,然后进行转换…………成功了!但也有个小问题,由于读取的buffer长度是截断的,所以有可能导致即使是 utf8 的文本,也不能成功用 utf8 解出来,因为你可能恰好 buffer 到了一个字符编码的中间。

    最终,我的解决方案是一次性读取全部内容,这样就不会出错啦。

    当然,代价就是需要一次性将所有内容读进内存。对我来说问题不大,因为输入法码表通常并不是很大。如果有必要,其实也可以对 buffer 的大小或者位置进行一点偏移然后再试一次之类的。

    最终,代码是这样的:

    val buffer: ByteArray = inputStream.readAllBytes()
            inputStream.close()
            var content: String? = null
            try {
                content = Charsets.UTF_8.newDecoder().decode(ByteBuffer.wrap(buffer)).toString()
            } catch (_: Exception) {
                // do nothing try next one
            }
            try {
                content = Charsets.GB18030.newDecoder().decode(ByteBuffer.wrap(buffer)).toString()
            } catch (_: Exception) {
                // do nothing try next one
            }
            if (content == null) {
                return importFalse(context, "码表编码格式错误,请确定编码为 uft-8 不要有 BOM!")
            }

     

    Kotlin/Android 检测文本编码,首发于落格博客。

    其他推荐:
    1. Android 安卓开发板 读取串口
    2. 禁用 Android File Transfer 自动启动
    3. Exception in thread “main” java.lang.ArrayIndexOutOfBoundsException: 0
    4. swift4 urlSession get和post网络请求
    5. 我给落格输入法的用户群添加了个自动回复机器人



沪ICP备19023445号-2号
友情链接