Наиболее эффективное решение для чтения 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();
}
Ответы
Ответ 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();