用于将CLOB读取到String的最有效解决方案,以及在Java中将String读取到CLOB?

时间:2010-01-30 22:36:55

标签: java stringbuilder clob

我有一个很大的CLOB(超过32kB),我想用StringBuilder读取一个String。我如何以最有效的方式做到这一点?我不能使用StringBuilder的“int length”构造函数,因为我的CLOB的长度比“int”长,并且需要“long”值。

我对Java I / O类并不那么舒服,并希望获得一些指导。

编辑 - 我已尝试使用此代码进行clobToString():

private String clobToString(Clob data) {
    StringBuilder sb = new StringBuilder();
    try {
        Reader reader = data.getCharacterStream();
        BufferedReader br = new BufferedReader(reader);

        String line;
        while(null != (line = br.readLine())) {
            sb.append(line);
        }
        br.close();
    } catch (SQLException e) {
        // handle this exception
    } catch (IOException e) {
        // handle this exception
    }
    return sb.toString();
}

12 个答案:

答案 0 :(得分:44)

好的我会假设一般使用,首先你必须下载apache commons,你会发现一个名为IOUtils的实用程序类,它有一个名为copy()的方法;

现在的解决方案是:使用getAsciiStream()获取CLOB对象的输入流,并将其传递给copy()方法。

InputStream in = clobObject.getAsciiStream();
StringWriter w = new StringWriter();
IOUtils.copy(in, w);
String clobAsString = w.toString();

答案 1 :(得分:18)

我的回答只是一种相同的味道。但我通过序列化压缩内容来测试它并且它有效。所以我可以相信这个解决方案,不像第一个提供的解决方案(使用readLine),因为它会忽略换行并破坏输入。

/*********************************************************************************************
 * From CLOB to String
 * @return string representation of clob
 *********************************************************************************************/
private String clobToString(java.sql.Clob data)
{
    final StringBuilder sb = new StringBuilder();

    try
    {
        final Reader         reader = data.getCharacterStream();
        final BufferedReader br     = new BufferedReader(reader);

        int b;
        while(-1 != (b = br.read()))
        {
            sb.append((char)b);
        }

        br.close();
    }
    catch (SQLException e)
    {
        log.error("SQL. Could not convert CLOB to string",e);
        return e.toString();
    }
    catch (IOException e)
    {
        log.error("IO. Could not convert CLOB to string",e);
        return e.toString();
    }

    return sb.toString();
}

答案 2 :(得分:17)

  

我不能对StringBuilder使用“int length”构造函数,因为我的CLOB长度超过int且需要long值。

如果CLOB长度大于int中的值,则CLOB数据也不适合String。您将不得不使用流式处理方法来处理这么多的XML数据。

如果CLOB的实际长度小于Integer.MAX_VALUE,只需将long强加到int,然后将(int)放在其前面。

答案 3 :(得分:15)

出了什么问题:

clob.getSubString(1, (int) clob.length());

例如,Oracle oracle.sql.CLOB在内部getSubString()上执行char[],内部oracle.jdbc.driver.T4CConnectionSystem.arraycopy()String中定义,然后包裹到System.arraycopy()。你的阅读速度永远不会超过CLOB

更新获取驱动程序ojdbc6.jar,并反编译{{1}}实施,并根据内部知识更快地研究哪种情况。

答案 4 :(得分:4)

如果你真的必须只使用标准库,那么你只需要扩展一下Omar的解决方案。 (Apache的IOUtils基本上只是一组方便的方法,节省了大量的编码)

您已经能够通过clobObject.getAsciiStream()

获取输入流

您只需要将字符“手动转移”到StringWriter:

InputStream in = clobObject.getAsciiStream();
Reader read = new InputStreamReader(in);
StringWriter write = new StringWriter();

int c = -1;
while ((c = read.read()) != -1)
{
    write.write(c);
}
write.flush();
String s = write.toString();

请记住

  1. 如果您的clob包含的字符多于符合字符串的字符,则无效。
  2. 分别用BufferedReader和BufferedWriter包装InputStreamReader和StringWriter以获得更好的性能。

答案 5 :(得分:4)

如果使用Mule,则以下是步骤。

按照以下步骤操作。

在连接器中启用流式传输,即progressiveStreaming = 2

Typecast DB2将CLOB返回给java.sql.Clob(IBM支持此类型转换)

将其转换为字符流(ASCII流有时可能不支持某些特殊字符)。所以你可以使用getCharacterStream()

这将返回一个“reader”对象,可以使用common-io(IOUtils)将其转换为“String”。

简而言之,使用groovy组件并添加下面的代码。

clobTest = (java.sql.Clob)payload.field1 
bodyText = clobTest.getCharacterStream() 
targetString = org.apache.commons.io.IOUtils.toString(bodyText)
payload.PAYLOADHEADERS=targetString return payload

注意:这里我假设“payload.field1”正在保存clob数据。

就是这样!

关心Naveen

答案 6 :(得分:1)

public static final String tryClob2String(final Object value)
{
    final Clob clobValue = (Clob) value;
    String result = null;

    try
    {
        final long clobLength = clobValue.length();

        if (clobLength < Integer.MIN_VALUE || clobLength > Integer.MAX_VALUE)
        {
            log.debug("CLOB size too big for String!");
        }
        else
        {
            result = clobValue.getSubString(1, (int) clobValue.length());
        }
    }
    catch (SQLException e)
    {
        log.error("tryClob2String ERROR: {}", e);
    }
    finally
    {
        if (clobValue != null)
        {
            try
            {
                clobValue.free();
            }
            catch (SQLException e)
            {
                log.error("CLOB FREE ERROR: {}", e);
            }
        }
    }

    return result;
}

答案 7 :(得分:1)

private String convertToString(java.sql.Clob data)
{
    final StringBuilder builder= new StringBuilder();

    try
    {
        final Reader         reader = data.getCharacterStream();
        final BufferedReader br     = new BufferedReader(reader);

        int b;
        while(-1 != (b = br.read()))
        {
            builder.append((char)b);
        }

        br.close();
    }
    catch (SQLException e)
    {
        log.error("Within SQLException, Could not convert CLOB to string",e);
        return e.toString();
    }
    catch (IOException e)
    {
        log.error("Within IOException, Could not convert CLOB to string",e);
        return e.toString();
    }
    //enter code here
    return builder.toString();
}

答案 8 :(得分:0)

public static String readClob(Clob clob) throws SQLException, IOException {
    StringBuilder sb = new StringBuilder((int) clob.length());
    Reader r = clob.getCharacterStream();
    char[] cbuf = new char[2048];
    int n;
    while ((n = r.read(cbuf, 0, cbuf.length)) != -1) {
        sb.append(cbuf, 0, n);
    }
    return sb.toString();
}

上述方法也非常有效。

答案 9 :(得分:0)

使用apache commons.io的友好助手方法

Reader reader = clob.getCharacterStream();
StringWriter writer = new StringWriter();
IOUtils.copy(reader, writer);
String clobContent = writer.toString();

答案 10 :(得分:0)

 public static String clobToString(final Clob clob) throws SQLException, IOException {
        try (final Reader reader = clob.getCharacterStream()) {
            try (final StringWriter stringWriter = new StringWriter()) {
                IOUtils.copy(reader, stringWriter);
                return stringWriter.toString();
            }
        }
    }

答案 11 :(得分:-1)

CLOB就像文件一样,你可以像这样轻松阅读部分内容

// read the first 1024 characters
String str = myClob.getSubString(0, 1024);

你可以像这样覆盖它

// overwrite first 1024 chars with first 1024 chars in str
myClob.setString(0, str,0,1024);

我不建议使用StringBuilder并填写它直到你得到一个Exception,几乎就像盲目地添加数字直到你得到溢出。 Clob就像一个文本文件,读取它的最好方法是使用缓冲区,以防你需要处理它,否则你可以将它流式传输到这样的本地文件

int s = 0;
File f = new File("out.txt");
FileWriter fw new FileWriter(f);

while (s < myClob.length())
{
    fw.write(myClob.getSubString(0, 1024));
    s += 1024;
}

fw.flush();
fw.close();