Копирование потока в поток

Речь в данном топике пойдет о потоках в смысле Stream, а не в смысле Thread. Часто требуется направить содержимое файла в сокет, или клавиатурный ввод в файл, или содержимое байтового массива в другой байтовый массив. Короче говоря один поток байт в другой. Есть несколько способов сделать это.


Вот, например, метод, который я стырил лет 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 свернуть / развернуть
+
0
Ха — первый пример кода навивает тоску — похоже очень на C — разве что malloc'ов не хватает )))
avatar

Sergei_T

  • 08 мая 2010, 22:55
+
0
A Java по сути и родилась как C без malloc'ов (о выделении памяти и сборке «мусора» заботится виртуальная машина) и без указателей/разыменований в синтаксисе (все объекты — ссылки на байтовые структуры) . Всё остальное — производные.
avatar

yababay

  • 08 мая 2010, 22:59
+
0
Попахивает на Visual C плюх-плюх...
avatar

Markony

  • 09 мая 2010, 08:17

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.