如何使用 java 中的编码将 clob 转换为字符串

How to convert clob to string with encoding in java

我们正在进行大量 xml 处理,将 clob 转换为字符串的逻辑如下所示。

import java.sql.Clob
import org.apache.commons.io.IOUtils

String extractXml(Clob xmlClob) {

    log.info "DefaultCharset: " + groovy.util.CharsetToolkit.getDefaultSystemCharset()

    String sourceXml
    try {
        sourceXml = new String(IOUtils.toByteArray(xmlClob?.getCharacterStream()), encoding)            // 1. Encoding not working
        sourceXml = new String(IOUtils.toByteArray(xmlClob?.getCharacterStream(), encoding), encoding)  // 2. Encoding working
    } catch (Exception e) {
        ...
    }

    return sourceXml
}

我的查询:

一个。我不确定为什么 (1) 不起作用,即使我使用的是 getCharacterStream() 而不是 getAsciiStream()。 但是 (2) 似乎工作正常可能是我正在使用系统编码的显式覆盖?

b。解决方案 (2) 看起来有点奇怪,因为您指定了 2 倍的编码格式(一个用于字节数组,一个用于创建字符串)。 我不确定是否有任何性能问题或想知道是否有更好的方法来编写它们?

c。我考虑过不使用 Apache-commons 库并使用简单的 java 包解决方案。 但令人惊讶的是,我没有给出任何明确的编码,但它似乎工作得很好。 是因为它 "streams character -> straight to string buffering" 吗?

/*
 * working perfectly and retuns encoding correctly
 */
String extractXmlWithoutApacheCommons(Clob xmlClob) {

    log.info "DefaultCharset: " + groovy.util.CharsetToolkit.getDefaultSystemCharset()

    StringBuffer sb = new StringBuffer((int) xmlClob.length())
    try {
        Reader r = xmlClob.getCharacterStream()
        char[] cbuf = new char[2048]
        int n = 0

        while ((n = r.read(cbuf, 0, cbuf.length)) != -1) {
            if (n > 0) {
                sb.append(cbuf, 0, n)
            }
        }

    } catch (Exception e) {
        ...
    }

    return sb.toString()
}    

你们能不能解释一下以了解它们。

Clob 已有编码。它是您在数据库中指定的任何内容,一旦您在 Java 侧阅读它,它将成为 String(使用隐式 UTF-16 编码,这根本不重要)。

无论您认为自己使用所有这些编码技巧做什么都是错误且无用的。您只需要在将 bytes 转换为 chars 或相反时指定编码。您只处理 chars (除了您的第一个示例,您出于某种未知原因想将它们转换为字节)。

如果您想使用 IOUtils,那么 readFully(Reader input, char[] buffer) 就是要使用的方法。

平台默认编码对整个问题没有影响,因为您根本不应该使用字节。

编辑: 使用标准 JDK 类 稍微 更现代的方法是使用 Reader.read(CharBuffer target) like

CharBuffer cb = CharBuffer.allocate((int) xmlClob.length());
while(r.read(cb) != -1)
    ;
return cb.toString();

但这并没有太大的不同(它看起来更好看)。