在Java中读取CLOB到字符串和字符串到CLOB的最有效解决方案?

在Java中读取CLOB到字符串和字符串到CLOB的最有效解决方案?,java,stringbuilder,clob,Java,Stringbuilder,Clob,我有一个大的CLOB(超过32kB),我想使用StringBuilder读取到一个字符串。我如何以最有效的方式完成这项工作?我不能为StringBuilder使用“int length”构造函数,因为CLOB的长度比“int”长,需要一个“long”值 我对Java I/O类不太熟悉,希望得到一些指导 编辑-我已尝试使用clobToString()的以下代码: 好的,我将假设一个通用的用法,首先您必须下载,在那里您将发现一个名为IOUtils的实用程序类,它有一个名为copy()的方法 现在的解

我有一个大的CLOB(超过32kB),我想使用StringBuilder读取到一个字符串。我如何以最有效的方式完成这项工作?我不能为StringBuilder使用“int length”构造函数,因为CLOB的长度比“int”长,需要一个“long”值

我对Java I/O类不太熟悉,希望得到一些指导

编辑-我已尝试使用clobToString()的以下代码:


好的,我将假设一个通用的用法,首先您必须下载,在那里您将发现一个名为IOUtils的实用程序类,它有一个名为copy()的方法

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

我不能为
StringBuilder
使用“int-length”构造函数,因为我的CLOB长度大于
int
并且需要
long

如果CLOB长度大于int中的fits,则CLOB数据也不会适合字符串。您必须使用流式方法来处理如此多的XML数据


如果CLOB的实际长度小于
Integer.MAX_VALUE
,只需将
long
置于
(int)
前面,将其强制为
int

如果您确实必须只使用标准库,那么您只需稍微扩展一下Omar的解决方案。(Apache的IOUtils基本上只是一组方便的方法,可以节省大量的编码)

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

您只需将字符“手动传输”到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();
记住

  • 如果clob包含的字符数超过了字符串所能容纳的字符数,则此操作无效
  • 分别使用BufferedReader和BufferedWriter包装InputStreamReader和StringWriter,以获得更好的性能

  • 我的回答也是一样。但我通过序列化压缩内容对其进行了测试,结果成功了。因此,我可以相信这个解决方案不同于第一个提供的解决方案(使用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();
    }
    
    有什么问题吗

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

    例如,Oracle
    Oracle.sql.CLOB
    对内部
    char[]
    执行
    getSubString()
    ,该内部
    char[]
    Oracle.jdbc.driver.T4CConnection
    和just
    System.arraycopy()
    中定义,然后换行到
    String
    。。。您的阅读速度永远不会超过
    System.arraycopy()

    更新获取驱动程序,反编译
    CLOB
    实现,并根据内部知识研究哪种情况更快

    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();
    }
    
    上述方法也非常有效。

    公共静态最终字符串tryClob2String(最终对象值)
    
    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;
    }
    
    { 最终Clob clobValue=(Clob)值; 字符串结果=null; 尝试 { 最终长clobLength=clobValue.length(); if(clobLengthInteger.MAX_值) { 调试(“CLOB大小对于字符串来说太大了!”); } 其他的 { 结果=clobValue.getSubString(1,(int)clobValue.length()); } } 捕获(SQLE异常) { 错误(“tryClob2String错误:{}”,e); } 最后 { if(clobValue!=null) { 尝试 { clobValue.free(); } 捕获(SQLE异常) { 错误(“无CLOB错误:{}”,e); } } } 返回结果; }
    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);
    
    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();
    
    你可以像这样覆盖它

    // 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);
    
    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();
    
    我不建议使用StringBuilder并在出现异常之前填充它,就像在出现溢出之前盲目地添加数字一样。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);
    
    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();
    
    ints=0;
    文件f=新文件(“out.txt”);
    FileWriter fw新的FileWriter(f);
    而(s
    如果使用Mule,以下是步骤

    遵循以下步骤

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

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

    将其转换为字符流(ASCII流有时可能不支持某些特殊字符)。因此,您可能需要使用getCharacterStream()

    这将返回一个“reader”对象,该对象可以使用公共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是使用ApacheCommons.io的友好助手方法

    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();
    }
    
    Reader reader = clob.getCharacterStream();
    StringWriter writer = new StringWriter();
    IOUtils.copy(reader, writer);
    String clobContent = writer.toString();
    

    一旦将CLOB读入字符串,您到底想做什么?您是指数据库意义上的CLOB,还是仅仅指“大字符串”?是的,它是来自DB2数据库的CLOB。CLOB包含一个大的XML字符串,将传递给JAXB。我想知道Java NIO中是否有对此有用的类。谢谢,这看起来不错。但是我对这个问题有了更多的了解,因为我更喜欢只使用标准库的解决方案。我已经加载了Apache Commons库,所以这是一个完美的解决方案。谢谢如果使用unicode,GetAsciStream会让您头疼。(或ascii以外的任何字符)我将
    InputStream
    更改为
    Reader
    并将
    clobObject.getascistream()
    更改为
    clobObject.getCharacterStream()
    ,以防止编码问题。事实上,如果CLOB大小大于2^32字节,您会遇到大问题我建议将其写入文件,如果他需要处理整个CLOB,那么看起来与我在