2011-11-02 37 views
25

Tôi đang tìm lớp Java huyền diệu mà sẽ cho phép tôi làm điều gì đó như thế này:Làm thế nào để ghi dữ liệu vào hai đối tượng java.io.OutputStream cùng một lúc?

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

MultiOutputStream outStream = new MultiOutputStream(byteStream, fileStream); 

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

Về cơ bản, tôi muốn tee cho OutputStream s trong Java. Bất kỳ ý tưởng?

Cảm ơn!

Trả lời

2

Cuộn của riêng bạn, về cơ bản là tầm thường. Sử dụng ArrayList<OutputStream> hoặc bất kỳ thứ gì phổ biến hiện nay để lưu trữ tất cả các luồng bạn muốn và viết phương thức write để lặp lại tất cả các luồng đó, viết cho từng luồng.

+14

Không có gì trong I/O là không quan trọng. Ngay cả khi nó có vẻ như vậy lúc đầu tiên. –

+0

Điều này không thực sự trả lời câu hỏi về cách viết cho tất cả chúng đồng thời. – Ataraxia

+0

@ZettaSuro "viết phương thức ghi để lặp lại tất cả chúng, viết cho từng." Bạn có thực sự cần tôi để viết ra 'for' loop cho bạn? – Kevin

14

Chỉ cần cuộn của riêng bạn. Không có ma thuật nào cả. Sử dụng Apache's TeeOutputStream về cơ bản bạn sẽ sử dụng mã bên dưới. Tất nhiên bằng cách sử dụng thư viện Apache Commons I/O, bạn có thể tận dụng các lớp khác, nhưng đôi khi nó là tốt đẹp để thực sự viết một cái gì đó cho chính mình. :)

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

thử nghiệm với các lớp trên như sau

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

sẽ in Hello World!Hello World!.

(Lưu ý: ghi đè close() có thể sử dụng một số dịch vụ chăm sóc tho' :)

+0

Việc ghi phải được đồng bộ hóa. –

+0

Bạn có thể đơn giản hóa điều đó. Có nó mở rộng 'FilterOutputStream'; xây dựng nó với 'super (out)'; loại bỏ thành viên 'out'; và thay đổi tất cả các tham chiếu 'out.' thành' super.'. – EJP

+0

@Dave Phụ thuộc vào trường hợp sử dụng. EJP Tôi thích nó theo cách này tốt hơn, nhưng điều đó cũng có tác dụng. –

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

Chỉ cần tìm thấy chủ đề này + Nhà tôi đã phải đối mặt với cùng một vấn đề. Nếu ai đó muốn thấy giải pháp (mã java7) của tôi:

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

} 

Hoạt động tốt cho đến nay, chỉ cần kiểm tra một số hoạt động cơ bản, ví dụ thiết lập một MultiOutputStream từ System.out Stream và 2 PrintStreams mỗi bản ghi vào một bản ghi riêng biệt. Tôi đã sử dụng

System.setOut(multiOutputStream); 

để ghi vào màn hình đầu cuối và hai nhật ký không hoạt động.

+0

tôi đã cố gắng sử dụng mã của bạn, tuy nhiên nó cho tôi một lỗi biên dịch - Phương thức setOut (PrintStream) trong kiểu System không áp dụng cho các đối số (MultiOutputStream) – Raj

Các vấn đề liên quan