在Java中读取CLOB到字符串和字符串到CLOB的最有效解决方案?
我有一个大的CLOB(超过32kB),我想使用StringBuilder读取到一个字符串。我如何以最有效的方式完成这项工作?我不能为StringBuilder使用“int length”构造函数,因为CLOB的长度比“int”长,需要一个“long”值 我对Java I/O类不太熟悉,希望得到一些指导 编辑-我已尝试使用clobToString()的以下代码:在Java中读取CLOB到字符串和字符串到CLOB的最有效解决方案?,java,stringbuilder,clob,Java,Stringbuilder,Clob,我有一个大的CLOB(超过32kB),我想使用StringBuilder读取到一个字符串。我如何以最有效的方式完成这项工作?我不能为StringBuilder使用“int length”构造函数,因为CLOB的长度比“int”长,需要一个“long”值 我对Java I/O类不太熟悉,希望得到一些指导 编辑-我已尝试使用clobToString()的以下代码: 好的,我将假设一个通用的用法,首先您必须下载,在那里您将发现一个名为IOUtils的实用程序类,它有一个名为copy()的方法 现在的解
好的,我将假设一个通用的用法,首先您必须下载,在那里您将发现一个名为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();
记住
我的回答也是一样。但我通过序列化压缩内容对其进行了测试,结果成功了。因此,我可以相信这个解决方案不同于第一个提供的解决方案(使用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());
?
例如,OracleOracle.sql.CLOB
对内部char[]
执行getSubString()
,该内部char[]
在Oracle.jdbc.driver.T4CConnection
和justSystem.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,那么看起来与我在