Наиболее эффективное решение для чтения CLOB в String и String в CLOB в Java? - PullRequest
39 голосов
/ 31 января 2010

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

Мне не очень комфортно с классами ввода / вывода Java, и я хотел бы получить некоторые рекомендации.

Редактировать - Я пытался использовать этот код для 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();
}

Ответы [ 11 ]

44 голосов
/ 31 января 2010

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

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

InputStream in = clobObject.getAsciiStream();
StringWriter w = new StringWriter();
IOUtils.copy(in, w);
String clobAsString = w.toString();
18 голосов
/ 10 декабря 2012

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

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

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

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

15 голосов
/ 01 июля 2014

Что не так с:

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

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

ОБНОВЛЕНИЕ Получить драйвер ojdbc6.jar , декомпилировать реализацию CLOB и изучить, какой случай будет быстрее, на основе внутренних знаний.

4 голосов
/ 13 апреля 2016

Если используется Mule, ниже приведены шаги.

Выполните следующие шаги.

Включить потоковую передачу в соединителе, т. Е .gressiveStreaming = 2

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

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

Это вернет объект «reader», который можно преобразовать в «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" содержит данные сгустка.

Вот и все!

С уважением, Навин

4 голосов
/ 31 января 2010

Если вы действительно должны использовать только стандартные библиотеки, то вам просто нужно немного расширить решение Омара. (IOUtils в Apache - это просто набор удобных методов, которые экономят на кодировании)

Вы уже можете получить входной поток через 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. Если ваш клоб содержит больше символов, чем поместится в строку, это не сработает.
  2. Оберните InputStreamReader и StringWriter с BufferedReader и BufferedWriter соответственно для лучшей производительности.
1 голос
/ 04 декабря 2017
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 голос
/ 13 ноября 2015
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;
}
0 голосов
/ 31 июля 2018

Дружественный вспомогательный метод с использованием apache commons.io

Reader reader = clob.getCharacterStream();
StringWriter writer = new StringWriter();
IOUtils.copy(reader, writer);
String clobContent = writer.toString();
0 голосов
/ 05 января 2016

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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...