Подтвердить что ты не робот

Наиболее эффективное решение для чтения CLOB в String и String для CLOB в Java?

У меня есть большой CLOB (более 32 КБ), который я хочу прочитать в String, используя StringBuilder. Как мне сделать это наиболее эффективным способом? Я не могу использовать конструктор "длина строки" для StringBuilder, так как длина моего CLOB больше, чем "int" и требует "длинного" значения.

Я не настолько удобен для классов 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();
}
4b9b3361

Ответ 1

Я не могу использовать конструктор "длина строки" для StringBuilder, так как длина моего CLOB больше, чем int и требует значения long.

Если длина CLOB больше, чем подходит для int, данные CLOB также не будут помещаться в строку. Вам нужно будет использовать потоковый подход для обработки этих XML-данных.

Если фактическая длина CLOB меньше, чем Integer.MAX_VALUE, просто запустите long до int, положив (int) перед ним.

Ответ 2

Хорошо, я предполагаю, что вам нужно сначала использовать apache commons, там вы найдете класс утилиты с именем IOUtils, который имеет метод с именем copy();

Теперь решение: получить входной поток объекта CLOB с помощью getAsciiStream() и передать его методу copy().

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

Ответ 3

Мой ответ - это просто аромат того же самого. Но я тестировал его с сериализацией сжатого содержимого, и он работал. Поэтому я могу доверять этому решению в отличие от предложенного в первую очередь (который использует 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();
}

Ответ 4

Что случилось с:

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

?

Например, Oracle oracle.sql.CLOB создайте getSubString() из внутреннего char[], который определен в oracle.jdbc.driver.T4CConnection и просто System.arraycopy(), а затем оберните на String... Вы никогда не получите более быстрое чтение, а затем System.arraycopy().

UPDATE Получить драйвер ojdbc6.jar и декомпилировать реализацию CLOB и изучить, в каком случае будет работать быстрее по знаниям внутри.

Ответ 5

Если вы действительно должны использовать только стандартные библиотеки, вам просто нужно немного расширить решение 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 содержит больше символов, чем подходит для строки, это не сработает.
  • Оберните InputStreamReader и StringWriter с BufferedReader и BufferedWriter соответственно для лучшей производительности.

Ответ 6

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

При использовании Mule ниже приведены этапы.

Следуйте инструкциям ниже.

Включить потоковое воспроизведение в соединителе, то есть progressiveStreaming = 2

Typecast DB2 вернул CLOB в java.sql.Clob(IBM поддерживает этот тип)

Преобразуйте это в поток символов (поток ASCII иногда может не поддерживать некоторые специальные символы). Таким образом, вы можете использовать getCharacterStream()

Это вернет объект "читатель", который можно преобразовать в "String" с помощью 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.

Что это!

С уважением Naveen

Ответ 8

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

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

Ответ 10

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