Ответ 1
IOUtils.copy(in, out);
out.flush();
//...........
out.close(); // depends on your application
Где in
- FileInputStream, а out
- SocketOutputStream
.
IOUtils - это утилита из модуля Commons IO в Apache Commons.
ServletOutputStream output = response.getOutputStream();
output.write(byte[]);
Каков наиболее эффективный способ записи файла в javax.servlet.ServletOutputStream?
EDIT:
не будет ли это более эффективным, если бы использовался NIO?
IOUtils.copy(in, out);
out.flush();
//...........
out.close(); // depends on your application
Где in
- FileInputStream, а out
- SocketOutputStream
.
IOUtils - это утилита из модуля Commons IO в Apache Commons.
У вас есть ServletOutputStream. Единственный способ, которым вы можете написать это, - через java.io. *. Вы не можете использовать NIO на нем вообще (кроме как через обертку с Channels
, что бессмысленно: это все еще OutputStream
внизу, и вы просто добавляете обработку сверху). Фактический ввод-вывод привязан к сети, и ваши записи все равно буферизуются контейнером сервлета (чтобы он мог устанавливать заголовок Content-Length), поэтому поиск настроек производительности здесь бессмысленен.
Прежде всего, это не связано с сервлетами. Это относится к Java IO в целом. В конце концов, вы просто InputStream
и OutputStream
.
Что касается ответа, вы не единственный, кто задавался этим вопросом. На interwebs вы можете найти других, которые задавались вопросом о том же, но приложили все усилия, чтобы проверить/сравнить его сами:
В общем случае FileChannel
с 256-байтовым массивом, который считывается через завернутый ByteBuffer
и записывается непосредственно из массива байтов, это самый быстрый способ. Действительно, 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();
}
Если вы не хотите добавлять эту банку в свое приложение, вам необходимо скопировать ее вручную. Просто скопируйте реализацию метода отсюда: 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;
}
поместите эти 2 метода в один из ваших вспомогательных классов, и вам хорошо идти.