12

我从互联网上找到了下面的代码,它可以工作,但它不会将打印的控制台写入 omt.txt,它只会System.out.println在第二个 catch 块之后写入语句。如果你运行代码一次,你就会明白我的意思。所有我想要的是将控制台上的内容写入“omt.txt”文件,这就是......

在一些答案之后,我发现我的问题并不清楚,对此感到抱歉。我想将控制台输出保存到 omt.txt 文本文件。如果在控制台上打印“Hello 123”,它也应该在 omt.txt 文件中。换句话说,控制台上打印的任何内容都应该同时写入 om.txt 文件,或者可以在控制台执行之后但应该是1对1一样!

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;

public class Wrt_file {

    public static void main(String[] args) {
        System.out.println("THIS is what I see on the console. but not on TEXT file"); 

          File f = new File("omt.txt");
          if(!f.exists())
          {
            try {
                       f.createNewFile();
                } catch (Exception e) {
                    e.printStackTrace();
                }
          }

        try {
                FileOutputStream fos = new FileOutputStream(f);
                PrintStream ps = new PrintStream(fos);
                System.setOut(ps);
        } catch (Exception e) {
            e.printStackTrace();
        }
        System.out.println("THIS is what I see on the text file, but not on CONSOLE");      

        for (int i=0; i<10; i++){

            System.out.println("Testing");  
        }

    }

}
4

4 回答 4

23

在得知 OP 想要复制流后更新了答案

由于您想在两个流中写入数据,请尝试使用TeeOutputStreamApache Commons。在第二次尝试更改您的代码

try {
    FileOutputStream fos = new FileOutputStream(f);
    Runtime.getRuntime().addShutdownHook(new Thread(() -> {
        try {
            fos.flush();
        }
        catch (Throwable t) {
            // Ignore
        }
    }, "Shutdown hook Thread flushing " + f));
    //we will want to print in standard "System.out" and in "file"
    TeeOutputStream myOut=new TeeOutputStream(System.out, fos);
    PrintStream ps = new PrintStream(myOut, true); //true - auto-flush after println
    System.setOut(ps);
} catch (Exception e) {
    e.printStackTrace();
}

现在,结果System.out也将放在您的文件中。

于 2013-04-26T13:52:03.250 回答
2

原因是 :

The java.lang.System.setOut()方法重新分配“标准”输出流。

所以当你使用System.out.println它时只会在文本文件中打印

所以,如果你想在文本文件和控制台上打印,试试这个:

   

    FileOutputStream fos = new FileOutputStream(f);
    PrintStream ps = new PrintStream(fos);
    ps.println("THIS is what I see on the text file, but not on CONSOLE");
    System.out.println("THIS is what I see on the text file, but not on CONSOLE");

        for (int i = 0; i < 4; i++) {

            ps.println("Testing");
            System.out.println("Testing");
        } 
于 2013-04-26T13:37:33.180 回答
2

我对这个问题的解决方案是简单地定义您自己的 PrintStream 覆盖您正在使用的方法:

import java.io.FileNotFoundException;
import java.io.PrintStream;

public class DualStream extends PrintStream {
    public PrintStream consoleOutput = null;
    public PrintStream fileOutput = null;

    public DualStream(final PrintStream consoleOutput, final PrintStream fileOutput) throws FileNotFoundException {
        super(fileOutput, true);
        this.consoleOutput = consoleOutput;
        this.fileOutput = fileOutput;
    }

    @Override
    public void println() {
        consoleOutput.println();
        super.println();
    }

    @Override
    public void println(final Object output) {
       consoleOutput.println(output);
        super.println(output);
    }

    @Override
    public void println(final String output) {
        consoleOutput.println(output);
        super.println(output);
    }

    @Override
    public PrintStream printf(final String output, final Object... variables) {
        consoleOutput.printf(output, variables);
        super.printf(output, variables);
        return this;
    }
}

我们不覆盖的每个方法都将默认仅将输出写入文件。(默认为控制台,您可以在构造函数中切换 1 行或在构造函数调用中切换两个打印流位置)

现在只需定义 2 个打印流,其中一个将写入您的文件,让我们将其设为缓冲输出流以确保良好的性能:

public static void outputFile(final String file) {
    PrintStream CombinedOutput = null;
    try {
        CombinedOutput = new DualStream(System.out, new PrintStream(new BufferedOutputStream(new FileOutputStream(file))));
    } catch (final FileNotFoundException e) {
        e.printStackTrace();
    }
    System.setOut(CombinedOutput);
}
于 2021-01-02T07:04:18.290 回答
1

System.java中,这是out属性的声明:

public final static PrintStream out

您会看到它一次只能是一个 PrintSteam 对象。所以它要么是控制台要么是文件,但不是两者兼而有之。

在这一行,您有效地重新引导了目的地:

System.setOut(ps);

所以你的输出停止显示在控制台上。

于 2013-04-26T13:25:17.117 回答