Копирование потока в поток
Речь в данном топике пойдет о потоках в смысле Stream, а не в смысле Thread. Часто требуется направить содержимое файла в сокет, или клавиатурный ввод в файл, или содержимое байтового массива в другой байтовый массив. Короче говоря один поток байт в другой. Есть несколько способов сделать это.
Вот, например, метод, который я стырил лет 8 назад из одного проекта IBM:
Тут всё просто: кусками по 5000 байт один поток считывается и записывается в другой, а потом побайтно дописывается остаток, оказавшийся меньше размера буфера. Достоинство этого способа — в нем задействованы с незапамятных времен существующие в Java классы (InputStream, OutputStream, BufferedInputStream), поэтому метод подходит для любой Java-машины, если не ошибаюсь, даже для мобильных устройств.
Но время идет, Java развивается, в ней появляются новые пакеты, в частности java.nio (New Input/Output). Я долго закрывал глаза на его существование, но, в конце концов «руки дошли». Там копирование потоков осуществляется с помощью ByteBuffer:
По сути дела то же самое, но меньше количество строк.
Однако можно воспользоваться и готовым решением, которое пока почему-то не вошло в JDK, но есть в пакете Apache Commons:
Вот так, одной строкой Правда, для ее использования нужно скачать и подключить соответствуюшую библиотеку, а это иногда более хлопотно, чем скопипастить несколько строк кода. Поэтому «думайте сами, решайте сами», писать самому или искать стандартное решение.
Вот, например, метод, который я стырил лет 8 назад из одного проекта IBM:
public static void stream2Stream(InputStream is, OutputStream os) throws IOException{
BufferedInputStream bis = new BufferedInputStream(is);
byte barray[] = new byte[5000];
byte echo[] = null;
int i = 0;
int counter = 0;
while (i > -1) {
bis.mark(counter);
echo = barray;
if(counter == 0 && i == -1)break;
if(counter > 0)os.write(echo, 0, i);
i = bis.read(barray);
counter+=5000;
}
int b = 0;
bis.reset();
while(b != -1){
b = bis.read();
if(b > -1)os.write(b);
}
bis.close();
}
Тут всё просто: кусками по 5000 байт один поток считывается и записывается в другой, а потом побайтно дописывается остаток, оказавшийся меньше размера буфера. Достоинство этого способа — в нем задействованы с незапамятных времен существующие в Java классы (InputStream, OutputStream, BufferedInputStream), поэтому метод подходит для любой Java-машины, если не ошибаюсь, даже для мобильных устройств.
Но время идет, Java развивается, в ней появляются новые пакеты, в частности java.nio (New Input/Output). Я долго закрывал глаза на его существование, но, в конце концов «руки дошли». Там копирование потоков осуществляется с помощью ByteBuffer:
public void fastChannelCopy(final ReadableByteChannel src, final WritableByteChannel dest) throws IOException {
final ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1) {
buffer.flip();
dest.write(buffer);
buffer.compact();
}
buffer.flip();
while (buffer.hasRemaining())dest.write(buffer);
}
По сути дела то же самое, но меньше количество строк.
Однако можно воспользоваться и готовым решением, которое пока почему-то не вошло в JDK, но есть в пакете Apache Commons:
import org.apache.commons.io.IOUtils;
...
IOUtils.copy(InputStream in, OutputStream out);
Вот так, одной строкой Правда, для ее использования нужно скачать и подключить соответствуюшую библиотеку, а это иногда более хлопотно, чем скопипастить несколько строк кода. Поэтому «думайте сами, решайте сами», писать самому или искать стандартное решение.
Комментарии (3)
RSS свернуть / развернутьSergei_T
yababay
Markony
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.