2012-01-07 24 views
7

La corriente de entrada/salida gzip no funciona en búferes directos de Java.compresión en java nio buffers directos

¿Existe alguna implementación de algoritmo de compresión que opere directamente en búferes directos?

De esta forma no se sobrecargaría la copia de un búfer directo a una matriz de bytes java para la compresión.

+1

La compresión sin sobrecarga es imposible. Los búferes directos son, por definición, _ "un contenedor para una cantidad fija de datos de un tipo primitivo específico" _. Una transformación como una compresión o cifrado debe realizarse fuera del búfer. –

+1

entiendo. solo quiero hacer la compresión sin la penalidad adicional de copiar primero toda la matriz de búferes directos a una matriz de bytes Java – pdeva

+3

GZIPInputStream no crea una copia: se transmite directamente desde el archivo (en función de verificar la fuente). Así que me imagino que probablemente sea más rápido que crear tu propio búfer directo y asignarle un archivo. Si realmente desea usar un búfer directo, podría escribir su propio InputStream que fluye desde su búfer ... –

Respuesta

2

no me refiero a restar valor a su pregunta, pero ¿Es este realmente un buen punto de optimización en su programa? ¿Has verificado con un generador de perfiles que tienes un problema? Su pregunta tal como está formulada implica que no ha realizado ninguna investigación, sino que simplemente está adivinando que tendrá un problema de rendimiento o memoria al asignar un byte []. Dado que es probable que todas las respuestas en este hilo sean de algún tipo, realmente debes verificar que tengas un problema en antes de solucionarlo.

Volviendo a la pregunta, si quiere comprimir los datos "en su lugar" en un ByteBuffer, la respuesta es no, no hay capacidad para hacerlo en Java.

Si asigna el búfer como el siguiente:

byte[] bytes = getMyData(); 
ByteBuffer buf = ByteBuffer.wrap(bytes); 

Puede filtrar su byte [] a través de un ByteBufferInputStream como la respuesta anterior sugiere.

+0

lo acepto como respuesta, pero aún estoy esperando uno que proporciona una solución, por ejemplo, en forma de una biblioteca que opera usando jni en byte buffers. – pdeva

+0

Tenía curiosidad sobre esta pregunta porque quería encontrar una forma de convertir una carpeta a un archivo zip con el nombre solo en su lugar para eliminar rápidamente las carpetas grandes. –

+1

evitar copiar datos casi siempre es un impulso significativo para el rendimiento. Sin embargo, los datos que ya están en un búfer directo no se pueden comprimir sin copiarse a menos que lo haga el propio sistema operativo. – gregw

0

Si está utilizando ByteBuffers puede utilizar algunas envolturas simples de entrada/OutputStream como éstas:

public class ByteBufferInputStream extends InputStream { 

    private ByteBuffer buffer = null; 

    public ByteBufferInputStream(ByteBuffer b) { 
     this.buffer = b; 
    } 

    @Override 
    public int read() throws IOException { 
     return (buffer.get() & 0xFF); 
    } 
} 

public class ByteBufferOutputStream extends OutputStream { 

    private ByteBuffer buffer = null; 

    public ByteBufferOutputStream(ByteBuffer b) { 
     this.buffer = b; 
    } 

    @Override 
    public void write(int b) throws IOException { 
     buffer.put((byte)(b & 0xFF)); 
    } 

} 

prueba:

ByteBuffer buffer = ByteBuffer.allocate(1000); 
ByteBufferOutputStream bufferOutput = new ByteBufferOutputStream(buffer); 
GZIPOutputStream output = new GZIPOutputStream(bufferOutput); 
output.write("stackexchange".getBytes()); 
output.close(); 

buffer.position(0); 

byte[] result = new byte[ 1000 ]; 

ByteBufferInputStream bufferInput = new ByteBufferInputStream(buffer); 
GZIPInputStream input = new GZIPInputStream(bufferInput); 
input.read(result); 

System.out.println(new String(result)); 
+3

incluso no es útil envolver el bytebuffer en una secuencia, ya que está copiado internamente (a veces dos), sorta derrota el propósito del bytebuffer – bestsss

+0

Lo siento pero no lo entiendo, ¿cuándo ocurriría esa copia? Comprobé dos veces el código para InputStream, OutputStream e incluso las clases GZIP y no puedo encontrar ninguna copia. –

+0

así es como funciona, compruebe InflatedInputStream y la impl nativa tiene que copiar (o fijar, depende de la JVM/GC) el byte [] para pasarlo a zlib – bestsss