StringBuilderを使用して、文字列に読み取りたい大きなCLOB(32kB以上)があります。最も効率的な方法でこれを行うにはどうすればよいですか? CLOBの長さが「int」より長く、「long」値が必要なため、StringBuilderに「int length」コンストラクターを使用できません。
私は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の長さが
StringBuilder
より長く、int
値が必要なため、long
に「int length」コンストラクターを使用できません。
CLOBの長さがintに収まらない場合、CLOBデータもStringに収まりません。この大量のXMLデータを処理するには、ストリーミングアプローチを使用する必要があります。
CLOBの実際の長さがInteger.MAX_VALUE
より小さい場合は、(int)
を前に置いてlong
をint
に強制します。
一般的な使用法を想定します。最初に Apache commons をダウンロードする必要があります。IOUtilsという名前のユーティリティクラスにcopy()というメソッドがあります。
現在の解決策は、getAsciiStream()を使用してCLOBオブジェクトの入力ストリームを取得し、それをcopy()メソッドに渡すことです。
InputStream in = clobObject.getAsciiStream();
StringWriter w = new StringWriter();
IOUtils.copy(in, w);
String clobAsString = w.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());
?
たとえば、Oracle Oracle.sql.CLOB
は、char[]
とgetSubString()
で定義された内部Oracle.jdbc.driver.T4CConnection
に対してSystem.arraycopy()
を実行し、次にString
にラップします。 。System.arraycopy()
よりも速く読むことはありません。
[〜#〜] update [〜#〜]ドライバーの取得 ojdbc6.jar 、およびCLOB
の逆コンパイル実装、および内部の知識に基づいてどのケースがより速くなるかを研究します。
ESB Muleを使用している場合、以下の手順を実行します。
以下の手順に従ってください。
コネクタでストリーミングを有効にします。すなわち、progressiveStreaming = 2
タイプキャストDB2はJava.sql.ClobにCLOBを返しました(IBMはこの型キャストをサポートしています)
それを文字ストリームに変換します(ASCIIストリームはいくつかの特殊文字をサポートしない場合があります)。したがって、getCharacterStream()を使用できます。
これは、common-io(IOUtils)を使用して「String」に変換できる「reader」オブジェクトを返します。
要するに、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
本当に標準ライブラリのみを使用する必要がある場合は、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();
覚えておいてください
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();
}
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;
}
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();
}
上記のアプローチも非常に効率的です。
Apache commons.ioを使用したフレンドリーなヘルパーメソッド
Reader reader = clob.getCharacterStream();
StringWriter writer = new StringWriter();
IOUtils.copy(reader, writer);
String clobContent = writer.toString();