用于将CLOB读入String的最有效解决方案,以及Java中用于CLOB的字符串的最有效解决方案?
我有一个很大的CLOB(超过32kB),我想使用StringBuilder读取字符串。我如何以最有效的方式做到这一点?我无法使用StringBuilder的“int length”构造函数,因为CLOB的长度比“int”长,需要一个“long”值。用于将CLOB读入String的最有效解决方案,以及Java中用于CLOB的字符串的最有效解决方案?
我不喜欢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();
}
因为我CLOB的长度比
int
长,需要一个long
值,我不能用“INT长度”的构造函数StringBuilder
。
如果CLOB长度大于适合int的值,那么CLOB数据也不适合String。您必须使用流式方法来处理这么多的XML数据。
如果CLOB的实际长度超过Integer.MAX_VALUE
小,只是通过把(int)
在它的前面迫使long
到int
。
事实上,如果CLOB大小大于2^32字节,那么您遇到了很大的问题 – skaffman 2010-01-31 11:55:01
如果他需要整个CLOB来处理 – 2016-01-05 10:39:26
好,我会想一个通用,首先你要下载apache commons,在那里你会找到一个实用工具类名为IOUtils,它有一个名为copy()的方法;
现在解决方案是:使用getAsciiStream()获取CLOB对象的输入流并将其传递给copy()方法。
InputStream in = clobObject.getAsciiStream();
StringWriter w = new StringWriter();
IOUtils.copy(in, w);
String clobAsString = w.toString();
谢谢,那看起来不错。但是我更关注这个问题,因为我更喜欢只使用标准库的解决方案。 – Jonas 2010-01-31 09:46:57
我已经加载了Apache Commons库,所以这是一个完美的解决方案。谢谢!如果你使用unicode,getAsciiStream会给你带来麻烦。 (或者任何超出ascii的字符) – 2011-06-02 14:47:03
为了防止编码问题,我将'InputStream'改为'Reader','clobObject.getAsciiStream()'改为'clobObject.getCharacterStream()'。 – Dormouse 2014-06-11 07:52:03
如果您确实必须只使用标准库,那么您只需要扩展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();
记住,
- 如果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.sql.CLOB
使内部char[]
getSubString()
这oracle.jdbc.driver.T4CConnection
定义,只是System.arraycopy()
和明年换到String
...你永远不会得到更快的读取然后System.arraycopy()
。
UPDATE获取驱动ojdbc6.jar和反编译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();
}
上述方法也非常有效。
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就像是文件,你可以轻松地阅读它的部分是这样
// 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的建议并填写它,直到你得到一个例外,就像盲目添加数字,直到你溢出。 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();
,以下是步骤。
请按照以下步骤操作。
启用流在所述连接器即progressiveStreaming = 2
类型转换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数据。
就是这样!
问候纳文
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();
}
通常最好解释一个解决方案,而不是只发布一些匿名代码行。你可以阅读[我如何写一个好的答案](https://stackoverflow.com/help/how-to-answer),还有[完全解释基于代码的答案](https://meta.stackexchange.com /问题/ 114762 /解释-entirely-%E2%80%8C%E2%80%8Bcode为主,答案) – 2017-12-04 10:32:23
你想一旦你读CLOB为一个字符串到底该怎么做? – 2010-01-30 22:38:34
你是指数据库意义上的CLOB,还是只是“大字符串”? – skaffman 2010-01-30 22:41:45
是的,它是来自DB2数据库的CLOB。 – Jonas 2010-01-30 22:42:49