J'ai un gros CLOB (plus de 32 Ko) que je veux lire dans une chaîne, en utilisant StringBuilder. Comment est-ce que je fais ceci de la manière la plus efficace? Je ne peux pas utiliser le constructeur "int length" pour StringBuilder car la longueur de mon objet CLOB est plus longue qu'un "int" et nécessite une valeur "long".
Je ne suis pas à l'aise avec les classes d'E/S Java et je souhaiterais obtenir des conseils.
Modifier - J'ai essayé avec ce code pour 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();
}
Je ne peux pas utiliser le constructeur "int length" pour
StringBuilder
car la longueur de mon objet CLOB est plus longue que celle d'unint
et nécessite une valeurlong
.
Si la longueur de CLOB est supérieure à ce qui convient à un int, les données CLOB ne tiendront pas non plus dans une chaîne. Vous devrez utiliser une approche de diffusion en continu pour traiter autant de données XML.
Si la longueur réelle de l'objet CLOB est inférieure à Integer.MAX_VALUE
, forcez simplement la variable long
à int
en mettant (int)
devant celle-ci.
Ok, je suppose un usage général. Vous devez d’abord télécharger Apache commons , vous y trouverez une classe d’utilitaires nommée IOUtils qui a une méthode nommée copy ();
Maintenant, la solution est: récupérez le flux d'entrée de votre objet CLOB à l'aide de getAsciiStream () et transmettez-le à la méthode copy ().
InputStream in = clobObject.getAsciiStream();
StringWriter w = new StringWriter();
IOUtils.copy(in, w);
String clobAsString = w.toString();
Ma réponse est juste un avant-goût de la même chose. Mais je l'ai testé avec la sérialisation d'un contenu compressé et cela a fonctionné. Je peux donc faire confiance à cette solution contrairement à celle proposée en premier (qui utilise readLine) car elle ignorera les sauts de ligne et corrompra l'entrée.
/*********************************************************************************************
* 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();
}
Quel est le problème avec:
clob.getSubString(1, (int) clob.length());
?
Par exemple, Oracle Oracle.sql.CLOB
exécute getSubString()
sur le char[]
interne défini dans Oracle.jdbc.driver.T4CConnection
et uniquement System.arraycopy()
et le bouclage suivant à String
... Vous ne lirez jamais plus vite que System.arraycopy()
.
UPDATE Obtenez le pilote ojdbc6.jar , décompilez la version CLOB
et étudiez le cas le plus rapide en fonction des connaissances internes.
Si vous ne devez utiliser que des bibliothèques standard, il vous suffit de développer un peu la solution de Omar. (Apache's IOUtils est fondamentalement juste un ensemble de méthodes pratiques qui permet d’économiser beaucoup de code)
Vous êtes déjà capable d’obtenir le flux d’entrée via clobObject.getAsciiStream()
Il vous suffit de "transférer manuellement" les caractères sur le 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();
Gardez à l'esprit que
Si vous utilisez Mule, voici les étapes.
Suivez les étapes ci-dessous.
Activer la diffusion en continu dans le connecteur, c'est-à-dire progressiveStreaming = 2
Typecast DB2 a renvoyé CLOB à Java.sql.Clob (IBM prend en charge cette conversion de type)
Convertissez cela en flux de caractères (les flux ASCII peuvent parfois ne pas prendre en charge certains caractères spéciaux). Donc, vous pouvez utiliser getCharacterStream ()
Cela retournera un objet "reader" qui peut être converti en "String" en utilisant common-io (IOUtils).
En bref, utilisez un composant groovy et ajoutez le code ci-dessous.
clobTest = (Java.sql.Clob)payload.field1
bodyText = clobTest.getCharacterStream()
targetString = org.Apache.commons.io.IOUtils.toString(bodyText)
payload.PAYLOADHEADERS=targetString return payload
Remarque: Je suppose ici que "payload.field1" contient des données de type clob.
C'est tout!
Cordialement Naveen
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();
}
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;
}
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();
}
L'approche ci-dessus est également très efficace.
Une méthode d'assistance amicale utilisant Apache commons.io
Reader reader = clob.getCharacterStream();
StringWriter writer = new StringWriter();
IOUtils.copy(reader, writer);
String clobContent = writer.toString();