50

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();
}
4

12 に答える 12

52

わかりました。一般的な使用法を想定します。最初にapachecommonsをダウンロードする必要があります。そこに、copy()という名前のメソッドを持つIOUtilsという名前のユーティリティクラスがあります。

解決策は次のとおりです。getAsciiStream()を使用してCLOBオブジェクトの入力ストリームを取得し、それをcopy()メソッドに渡します。

InputStream in = clobObject.getAsciiStream();
StringWriter w = new StringWriter();
IOUtils.copy(in, w);
String clobAsString = w.toString();
于 2010-01-30T22:54:03.537 に答える
32

どうしたの:

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

?

たとえば、Oracleoracle.sql.CLOBgetSubString()内部char[]で定義されたものをoracle.jdbc.driver.T4CConnection実行しSystem.arraycopy()、次のラップをString... より速く読み取ることはありませんSystem.arraycopy()

更新ドライバーojdbc6.jarを取得し、実装を逆コンパイルCLOBし、内部知識に基づいてどのケースがより高速になるかを調べます。

于 2014-07-01T15:41:31.323 に答える
21

私の答えは、同じ味です。しかし、圧縮されたコンテンツをシリアル化してテストしたところ、機能しました。したがって、最初に提供されたもの (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();
}
于 2012-12-10T03:42:23.757 に答える
20

StringBuilderCLOBの長さがaより長く、値intが必要なため、「intlength」コンストラクターを使用できません。long

CLOBの長さがintに収まるよりも大きい場合、CLOBデータも文字列に収まりません。これだけ多くのXMLデータを処理するには、ストリーミングアプローチを使用する必要があります。

CLOBの実際の長さが、よりも小さい場合は、CLOBの前に置くことでtoをInteger.MAX_VALUE強制します。longint(int)

于 2010-01-31T11:19:03.690 に答える
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();

心に留めておいてください

  1. 文字列に収まるよりも多くの文字が clob に含まれている場合、これは機能しません。
  2. パフォーマンスを向上させるために、InputStreamReader と StringWriter をそれぞれ BufferedReader と BufferedWriter でラップします。
于 2010-01-31T12:09:56.020 に答える
4

Mule を使用する場合の手順は次のとおりです。

以下の手順に従ってください。

コネクタでストリーミングを有効にします。つまり、progressiveStreaming=2

型キャスト DB2 は CLOB を java.sql.Clob に返しました (IBM はこの型キャストをサポートしています)

それを文字ストリームに変換します (ASCII ストリームでは一部の特殊文字がサポートされない場合があります)。したがって、 getCharacterStream() を使用できます

これは、common-io (IOUtils) を使用して「文字列」に変換できる「リーダー」オブジェクトを返します。

つまり、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 データを保持していると想定しています。

それでおしまい!

よろしくナビーン

于 2016-04-13T14:35:53.760 に答える
2

apache commons.io を使用した使いやすいヘルパー メソッド

Reader reader = clob.getCharacterStream();
StringWriter writer = new StringWriter();
IOUtils.copy(reader, writer);
String clobContent = writer.toString();
于 2018-07-31T13:06:04.073 に答える
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();
            }
        }
    }
于 2021-01-12T17:57:06.157 に答える
-2

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();
于 2016-01-05T10:51:41.317 に答える