Как записать данные в два объекта java.io.OutputStream одновременно? - PullRequest
31 голосов
/ 03 ноября 2011

Я ищу волшебный класс Java, который позволил бы мне сделать что-то вроде этого:

ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
FileOutputStream fileStream = new FileOutputStream(new File("/tmp/somefile"));

MultiOutputStream outStream = new MultiOutputStream(byteStream, fileStream);

outStream.write("Hello world".getBytes());

По сути, я хочу tee для OutputStream с в Java. Есть идеи?

Спасибо!

Ответы [ 5 ]

39 голосов
/ 03 ноября 2011

Попробуйте Apache Commons TeeOutputStream .

21 голосов
/ 03 ноября 2011

Просто сверните свое. Там нет никакой магии вообще. Используя Apache TeeOutputStream , вы в основном будете использовать приведенный ниже код. Конечно, используя библиотеку ввода / вывода Apache Commons, вы можете использовать другие классы, но иногда приятно на самом деле написать что-то для себя. :)

public final class TeeOutputStream extends OutputStream {

  private final OutputStream out;
  private final OutputStream tee;

  public TeeOutputStream(OutputStream out, OutputStream tee) {
    if (out == null)
      throw new NullPointerException();
    else if (tee == null)
      throw new NullPointerException();

    this.out = out;
    this.tee = tee;
  }

  @Override
  public void write(int b) throws IOException {
    out.write(b);
    tee.write(b);
  }

  @Override
  public void write(byte[] b) throws IOException {
    out.write(b);
    tee.write(b);
  }

  @Override
  public void write(byte[] b, int off, int len) throws IOException {
    out.write(b, off, len);
    tee.write(b, off, len);
  }

  @Override
  public void flush() throws IOException {
    out.flush();
    tee.flush();
  }

  @Override
  public void close() throws IOException {
    try {
      out.close();
    } finally {
      tee.close();
    }
  }
}

Тестирование с указанным классом со следующим

public static void main(String[] args) throws IOException {
  TeeOutputStream out = new TeeOutputStream(System.out, System.out);
  out.write("Hello world!".getBytes());
  out.flush();
  out.close();
}

напечатает Hello World!Hello World!.

(Примечание: переопределенный close() может использовать некоторую осторожность, хотя ':)

3 голосов
/ 25 января 2013

Только что нашел эту ветку, потому что мне пришлось столкнуться с той же проблемой. Если кто-то хочет увидеть мое решение (код java7):

package Core;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;

public class MultiOutputStream extends OutputStream {

private List<OutputStream> out;

public MultiOutputStream(List<OutputStream> outStreams) {

    this.out = new LinkedList<OutputStream>();

    for (Iterator<OutputStream> i = outStreams.iterator(); i.hasNext();) {
        OutputStream outputStream = (OutputStream) i.next();

        if(outputStream == null){
            throw new NullPointerException();
        }
        this.out.add(outputStream);
    }
}

@Override
public void write(int arg0) throws IOException {

    for (Iterator<OutputStream> i = out.iterator(); i.hasNext();) {
        OutputStream var = (OutputStream) i.next();

        var.write(arg0);
    }
}

@Override
public void write(byte[] b) throws IOException{

    for (Iterator<OutputStream> i = out.iterator(); i.hasNext();) {
        OutputStream var = (OutputStream) i.next();

        var.write(b);
    }
}

@Override
public void write(byte[] b, int off, int len) throws IOException{

    for (Iterator<OutputStream> i = out.iterator(); i.hasNext();) {
        OutputStream var = (OutputStream) i.next();

        var.write(b, off, len);
    }
}

@Override
public void close() throws IOException{

    for (Iterator<OutputStream> i = out.iterator(); i.hasNext();) {
        OutputStream var = (OutputStream) i.next();

        var.close();
    }
}

@Override
public void flush() throws IOException{

    for (Iterator<OutputStream> i = out.iterator(); i.hasNext();) {
        OutputStream var = (OutputStream) i.next();

        var.flush();
    }
}

}

Пока работает отлично, только что протестировал некоторые основные операции, например, установка MultiOutputStream из потока System.out и 2 PrintStream, каждый из которых записывает в отдельный журнал. Я использовал

System.setOut(multiOutputStream);

для записи на экран моего терминала и двух журналов, которые работали без проблем.

2 голосов
/ 03 ноября 2011

Бросьте свои собственные, это в основном тривиально.Используйте ArrayList<OutputStream> или что-либо еще популярное в настоящее время, чтобы сохранить все потоки, которые вы хотите, и напишите метод write, чтобы перебрать все из них и записать каждый из них.

0 голосов
/ 28 июня 2012
final ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
final FileOutputStream fileStream = new FileOutputStream(new File("/tmp/somefile"));
OutputStream outStream = new OutputStream() {

    public void write(int b) throws IOException {
        byteStream.write(b);
        fileStream.write(b);
    }
};
outStream.write("Hello world".getBytes());
...