web-dev-qa-db-ja.com

JavaでCLOBからString、およびStringからCLOBを読み取るための最も効率的なソリューションは?

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

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

CLOBの長さがintに収まらない場合、CLOBデータもStringに収まりません。この大量のXMLデータを処理するには、ストリーミングアプローチを使用する必要があります。

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

17
Barend

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

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

InputStream in = clobObject.getAsciiStream();
StringWriter w = new StringWriter();
IOUtils.copy(in, w);
String clobAsString = w.toString();
45
Omar Al Kababji

私の答えは同じものです。しかし、圧縮されたコンテンツをシリアル化してテストし、機能しました。したがって、最初に提供された(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();
}
18
Stan Sokolov

どうしたの:

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の逆コンパイル実装、および内部の知識に基づいてどのケースがより速くなるかを研究します。

17
gavenkoa

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

4
Naveen K Reddy

本当に標準ライブラリのみを使用する必要がある場合は、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でラップして、パフォーマンスを向上させます。
4
Edwin Lee
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();
}
1
Hemant Tripathi
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;
}
1
kayz1
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();
}

上記のアプローチも非常に効率的です。

0
Rohit

Apache commons.ioを使用したフレンドリーなヘルパーメソッド

Reader reader = clob.getCharacterStream();
StringWriter writer = new StringWriter();
IOUtils.copy(reader, writer);
String clobContent = writer.toString();
0
fl0w