简体   繁体   English

PrintWriter到多个文件

[英]PrintWriter to multiple files

I need to write the same text to multiple files (or streams). 我需要将相同的文本写入多个文件(或流)。 Sometimes I need to use Writer, sometimes a PrintWriter, sometimes a OutputStream... 有时我需要使用Writer,有时需要PrintWriter,有时需要OutputStream ...

One way to do this wold be to extend a PrintWriter to have an array of PrintWriters and overridde each method as follows: 一种解决方法是将PrintWriter扩展为具有PrintWriters数组,并按如下方法重写每个方法:

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

(and the same for Writer, OutputStream...) (与Writer,OutputStream相同)

Is there a better alternative? 有更好的选择吗? Is this already implemented in a library? 这已经在库中实现了吗?

You don't need to override all methods in PrintWriter , since all printXyz methods delegate to the basic write methods of the Writer API. 您不需要重写PrintWriter所有方法,因为所有printXyz方法都委托给Writer API的基本write方法。

Although: PrintWriter has a constructor PrintWriter(Writer out) . 虽然: PrintWriter具有构造函数PrintWriter(Writer out) So you need to implement only a new Writer with _one_method likes this: 因此,您只需要使用_one_method来实现一个新的Writer ,如下所示:

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

use this like this: 像这样使用:

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

This will take care of the Writers . 这将照顾Writers

You can do the same trick using OutputStream . 您可以使用OutputStream进行相同的操作。 You can also just implement MultiOutputStream , omit MultiWriter and use a delegation chain PrintWriter->OutputStreamWriter->MultiOutputStream . 您也可以只实现MultiOutputStream ,省略MultiWriter并使用委托链PrintWriter->OutputStreamWriter->MultiOutputStream This would be just one method in one class to implement and you get PrintWriter , Writer and OutputStream just for free. 这只是一个类中的一种实现方法,您可以免费获得PrintWriterWriterOutputStream

There are libraries out there already for this. 已经有用于此的库。 If you can use OSS then grab Apache Commons IO and take a look at the TeeOutputStream class. 如果可以使用OSS,请获取Apache Commons IO ,然后看看TeeOutputStream类。 Here's some sample code illustrating its use: 这是一些示例代码,说明其用法:

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

You can use TeeOutputStream anywhere a regular OutputStream is accepted, or wrap it in a Writer , depending on whats needed. 您可以在接受常规OutputStream任何地方使用TeeOutputStream ,也可以根据需要将其包装在Writer

If you can use a Logging Library... 如果可以使用日志记录库...

Use a logging library and define multiple appenders in its configuration. 使用日志记录库并在其配置中定义多个追加程序。

You could use Apache Log4J or LogBack to that effect (I'd recommend LogBack, but to each their own). 您可以使用Apache Log4JLogBack达到这种效果(我建议使用LogBack,但要分别使用它们)。

If you are forced to use PrintWriter... 如果您被迫使用PrintWriter ...

The unfortunately your solution is the best. 不幸的是,您的解决方案是最好的。

There's an alternative, but it's not pretty. 有一个替代方法,但这并不漂亮。 If you are forced to pass a PrintWriter, short of providing an extension to add to the JRE's trusted libs at load time to replace PrintWriter with a class doing in effect what you suggest, I don't think you have much choice. 如果您被迫传递PrintWriter,而没有提供在加载时添加到JRE的受信任库中的扩展,以实际上执行您所建议的类替换 PrintWriter ,那么我认为您没有太多选择。

Well, actually you could do this easily: 好吧,实际上您可以轻松地做到这一点:

instead of overriding all methods of PrintWriter class, you could override only one method of class Writer : 而不是重写PrintWriter类的所有方法,您可以重写Writer类的一个方法

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

because all other methods ( print(...) and other write(...) -s) use this one: 因为所有其他方法( print(...)和其他write(...) s)都使用此方法:

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

UPD: also flush() and close() methods. UPD:也是flush()close()方法。

For OutputStream the same situation with method public void write(int b) 对于OutputStream ,与方法public void write(int b)相同的情况

I prefer composition to extension. 我更喜欢构图而不是扩展。 Here is another option: 这是另一个选择:

public class 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);
    }

    public void write((char cbuf[], int off, int len)
    {
        if (listPrintWriter != null)
        {
            for (PrintWriter printWriter : listPrintWriter)
            {
                printWriter.write(cbuf, off, len);
            }
        }

        if (listWriter != null)
        {
            for (Writer writer : listWriter)
            {
                writer.write(cbuf, off, len);
            }
        }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM