4

我需要将相同的文本写入多个文件(或流)。有时我需要使用 Writer,有时是 PrintWriter,有时是 OutputStream...

一种方法是扩展 PrintWriter 以具有 PrintWriter 数组并覆盖每个方法,如下所示:

class MutiplePrintWriter extends PrintWriter {
    private PrintWriter[] outs;
    public MutiplePrintWriter(PrintWriter[] outs) { this.out = out; }

    public void print(boolean b) { for (PrintWriter out : outs) print(b); }
    public void print(char c) { for (PrintWriter out : outs) print(c); }
    public void print(char[] s) { for (PrintWriter out : outs) print(s); }
    ...
}   

(对于 Writer、OutputStream 也是一样的......)

有更好的选择吗?这是否已经在库中实现?

4

5 回答 5

2

您不需要重写 中的所有方法PrintWriter,因为所有printXyz方法都委托给API的基本write方法。Writer

虽然:PrintWriter有一个构造函数PrintWriter(Writer out)Writer因此,您只需要使用 _one_method实现一个新的方法,如下所示:

public class MultiWriter implements Writer {
    private List<Writer> delegates;

    public MultiWriter(List<Writer> delegates){
        this.delegates = delegates;
    }

    public void write(char cbuf[], int off, int len) throws IOException {
        for(Writer w: delegates){
            w.writer(cbuf, off, len);
        }
    }
}

像这样使用:

PrintWriter myPrinter = new PrintWriter(new MultiWriter(listOfDelegates));
myPrintWriter.println("Hello World!");

这将处理Writers.

您可以使用OutputStream. 您也可以只实现MultiOutputStream、省略MultiWriter和使用委托链PrintWriter->OutputStreamWriter->MultiOutputStream。这只是一个类中的一种方法,您可以免费PrintWriter获得。WriterOutputStream

于 2013-06-07T14:02:52.573 回答
2

为此已经有图书馆。如果您可以使用 OSS,请获取Apache Commons IO并查看TeeOutputStream类。下面是一些示例代码来说明它的使用:

public class TeeOutputStreamTest {

   @Test
   public void testPrintToMultipleStreams() throws Exception {
      final String fileName1 = "/tmp/fileOne.txt";
      final String fileName2 = "/tmp/fileTwo.txt";
      final String fileName3 = "/tmp/fileThree.txt";

      final TeeOutputStream tos = new TeeOutputStream(new FileOutputStream(
              fileName1), new TeeOutputStream(new FileOutputStream(fileName2),
              new FileOutputStream(fileName3)));
      final PrintWriter writer = new PrintWriter(tos);

      writer.println("Hello World");
      writer.close();
   }
}

您可以TeeOutputStream在任何接受常规OutputStream的地方使用,或将其包装在 a 中Writer,具体取决于需要什么。

于 2013-06-07T14:14:46.990 回答
1

好吧,实际上你可以很容易地做到这一点:

而不是覆盖类的所有方法PrintWriter,您可以只覆盖类的一种方法Writer

public void write(char cbuf[], int off, int len);

因为所有其他方法(print(...)和其他write(...)-s)都使用这个:

public void write(char cbuf[], int off, int len) {
   for (Writer out : outs) out.write(cbuf, off, len);
}

UPD:flush()close()方法。

对于OutputStream与方法相同的情况public void write(int b)

于 2013-06-07T13:53:22.367 回答
1

如果您可以使用日志库...

使用日志库并在其配置中定义多个附加程序。

你可以使用Apache Log4JLogBack来达到这个效果(我推荐 LogBack,但每个人都有自己的)。

如果您被迫使用 PrintWriter...

不幸的是,您的解决方案是最好的。

有一个替代方案,但它并不漂亮。如果您被迫通过 PrintWriter,没有提供扩展以在加载时添加到 JRE 的受信任库以替换 PrintWriter为实际执行您建议的类,我认为您没有太多选择。

于 2013-06-07T13:44:33.063 回答
0

我更喜欢组合而不是扩展。这是另一种选择:

公共类 MultiWriter
{
    List<PrintWriter> listPrintWriter = new LinkedList<PrintWriter>;
    List<Writer> listWriter = new LinkedList<Writer>;

    public void addPrintWriter(final PrintWriter newPrintWriter)
    {
        listPrintWriter.add(newPrintWriter);
    }

    public void addWriter(final Writer newWriter)
    {
        listWriter.add(newWriter);
    }

    公共无效写入((char cbuf [],int关闭,int len)
    {
        if (listPrintWriter != null)
        {
            对于 (PrintWriter printWriter : listPrintWriter)
            {
                printWriter.write(cbuf, off, len);
            }
        }

        if (listWriter != null)
        {
            对于(作家作家:listWriter)
            {
                writer.write(cbuf, off, len);
            }
        }
}
于 2013-06-07T14:02:12.227 回答