我有一个很大的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();
}
答案 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.T4CConnection
在System.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();
请记住
答案 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();