2011-01-10 17 views
14
ServletOutputStream output = response.getOutputStream(); 
output.write(byte[]); 

¿Cuál es la forma más efectiva de escribir un archivo en javax.servlet.ServletOutputStream?Forma más efectiva de escribir archivo en ServletOutputStream

EDIT:

no esta será más eficaz si se utiliza el NIO?

+0

nio no es una bala mágica que hace que todo se base más rápido. de hecho, nio generalmente es útil si necesita hacer que su código sea más "escalable" (por ejemplo, menos hilos que manejen más conexiones). para el código de subproceso único, io casi siempre es tan bueno o mejor (la excepción a esta regla puede ser transferencia de archivo a archivo). – jtahlborn

Respuesta

32
IOUtils.copy(in, out); 
out.flush(); 
//........... 
out.close(); // depends on your application 

Dónde in es el FileInputStream y out es el SocketOutputStream. IOUtils es una utilidad del módulo Commons IO en Apache Commons.

+6

+1, pero dos notas: es "Apache commons", y puede usar 'IOUtils.closeQuitely (..)' – Bozho

+0

@Bozho que solía llamarse Jakarta Commons hace muchos años :-) –

+0

que no funciona para yo, no quiero agregar el jar de Commons IO solo para esa funcionalidad. – IAdapter

0

Si no desea agregar ese jar a su aplicación, entonces tiene que copiarlo a mano. Sólo tienes que copiar la implementación del método de aquí: http://svn.apache.org/viewvc/commons/proper/io/trunk/src/main/java/org/apache/commons/io/IOUtils.java?revision=1004358&view=markup:

private static final int DEFAULT_BUFFER_SIZE = 1024 * 4; 

public static int copy(InputStream input, OutputStream output) throws IOException { 
    long count = copyLarge(input, output); 
    if (count > Integer.MAX_VALUE) { 
    return -1; 
    } 
    return (int) count; 
} 

public static long copyLarge(InputStream input, OutputStream output) 
    throws IOException { 
    byte[] buffer = new byte[DEFAULT_BUFFER_SIZE]; 
    long count = 0; 
    int n = 0; 
    while (-1 != (n = input.read(buffer))) { 
    output.write(buffer, 0, n); 
    count += n; 
    } 
    return count; 
} 

poner los 2 métodos en una de sus clases de ayuda y ya está bueno para ir.

+1

¿no será esto más efectivo si se usó el NIO? – IAdapter

+1

tuve resultados mixtos con nio :). Puede ser mejor o no. El código es definitivamente un poco más complejo y realmente necesita probar los resultados en su máquina para asegurarse de que es lo suficientemente bueno. Busque aquí algún código: http://thomaswabner.wordpress.com/2007/10/09/fast-stream-copy-using-javanio-channels/ –

+1

+1 ymmv, pero me ha costado mucho hacer la nio versión más rápida que las buenas corrientes antiguas –

3

En primer lugar, esto no está relacionado con los servlets. Esto se aplica a Java IO en general. Después de todo, solo tiene InputStream y OutputStream.

En cuanto a la respuesta, usted no es el único que se preguntó sobre esto. En la interwebs se puede encontrar a otras personas que se preguntaban sobre el mismo, pero se tomaron el esfuerzo para poner a prueba/referencia por sí mismos:

En general, un FileChannel con una gama de 256 K bytes que se lee a través de un ByteBuffer envuelto y escrito directamente desde la matriz de bytes es la manera más rápida. De hecho, NIO.

FileInputStream input = new FileInputStream("/path/to/file.ext"); 
FileChannel channel = input.getChannel(); 
byte[] buffer = new byte[256 * 1024]; 
ByteBuffer byteBuffer = ByteBuffer.wrap(buffer); 

try { 
    for (int length = 0; (length = channel.read(byteBuffer)) != -1;) { 
     System.out.write(buffer, 0, length); 
     byteBuffer.clear(); 
    } 
} finally { 
    input.close(); 
} 
+0

El primer enlace realmente parece recomendar un buffer 8K ya que el tiempo para copiar la diferencia entre 8 y 256K es mínimo. Eso parece tener sentido dado que la mayoría de los sistemas de archivos aún usan páginas de 4KB y clústeres de discos de 4KB. – AngerClown

+0

La diferencia es mínima. Sin embargo, OP está pidiendo una "forma efectiva", no una "manera eficiente". 8K sigue siendo rápido pero consume menos memoria en caso de un sitio ocupado. – BalusC

+0

¿Qué pasa con el uso de canales y Channel.transferTo? – IAdapter

4

Usted tiene un ServletOutputStream. La única forma de que puedas escribir es a través de java.io. *. No puede utilizar NIO en absoluto (excepto mediante el ajuste con Channels, que no tiene sentido: sigue siendo un OutputStream debajo y solo está agregando procesamiento en la parte superior). La E/S real está unida a la red, y sus escrituras están siendo almacenadas de forma predeterminada por el contenedor de servlets (para que pueda configurar el encabezado Content-Length), por lo que buscar ajustes en el rendimiento aquí no tiene sentido.

+0

puede usar los canales de nio. – IAdapter

+8

@ 01: Sí, puede usar los canales de NIO si usa Channels.newChannel (OutputStream). Que envuelve la corriente de salida en un canal. Todavía está hablando con un ByteArrayOutputStream subyacente. No hay ganancia de eficiencia en esta situación. No tiene sentido. – EJP

+0

es posible usar NIO usando los canales de NIO. –

Cuestiones relacionadas