2011-11-02 15 views
25

Busco clase Java mágica que permitirá que haga algo como esto:¿Cómo escribir datos en dos objetos java.io.OutputStream a la vez?

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

MultiOutputStream outStream = new MultiOutputStream(byteStream, fileStream); 

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

Básicamente, quiero tee para OutputStream s en Java. ¿Algunas ideas?

Gracias!

Respuesta

2

Hazlo tu mismo, es básicamente trivial. Utilice un ArrayList<OutputStream> o lo que sea popular hoy en día para almacenar todas las transmisiones que desee y escriba el método write para recorrer todas ellas, escribiendo en cada una.

+14

Nada en I/O es trivial. Incluso si parece tan al principio. –

+0

Esto realmente no responde la pregunta de cómo escribir en todos ellos simultáneamente. – Ataraxia

+0

@ZettaSuro "escribe el método de escritura para recorrer todos ellos, escribiendo a cada uno". ¿Realmente necesitas que escriba el ciclo 'for' para ti? – Kevin

14

Solo hazlo por ti mismo. No hay magia en absoluto. Usando Apache's TeeOutputStream básicamente usarías el siguiente código. Por supuesto, utilizando la biblioteca de E/S de Apache Commons puede aprovechar otras clases, pero a veces es bueno en realidad escribe algo para usted. :)

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 { 
    out.close(); 
    tee.close(); 
    } 
} 

Prueba con la clase anterior con la siguiente

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(); 
} 

imprimiría Hello World!Hello World!.

(Nota: el close() anulado podría utilizar algún tipo de atención aunque' :)

+0

Las escrituras deben estar sincronizadas. –

+0

Puede simplificar eso. Haga que extienda 'FilterOutputStream'; construirlo con 'super (out)'; deshacerse del miembro 'out'; y cambie todas las referencias '' out'' a las referencias 'super'. – EJP

+0

@Dave Depende del caso de uso. EJP Me gusta mejor de esta manera, pero eso también funcionaría. –

0
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()); 
3

Acabo de encontrar este hilo pd tuve que enfrentar el mismo problema. Si alguien quiere ver mi solución (código 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(); 
    } 
} 

} 

funciona bien hasta el momento, acabo de probar alguna operación básica, por ejemplo, configurar un MultiOutputStream desde System.out Stream y 2 PrintStreams, cada uno escribiendo en un registro separado. Solía ​​

System.setOut(multiOutputStream); 

escribir en mi pantalla del terminal y dos registros, que funcionaba sin ningún problema.

+0

intenté usar su código, sin embargo me da un error de compilación - El método setOut (PrintStream) en el tipo de sistema no es aplicable para los argumentos (MultiOutputStream) – Raj

Cuestiones relacionadas