【问题标题】:Writing to console and text file写入控制台和文本文件
【发布时间】:2013-04-26 13:21:05
【问题描述】:

我从互联网上找到了下面的代码,它可以工作,但它不会将打印的控制台写入 omt.txt,它只会在第二个 catch 块之后写入System.out.println 语句。如果你运行代码一次你就会明白我的意思是。我只想将控制台上的内容写到“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");  
        }

    }

}

【问题讨论】:

    标签: java file-io console fileoutputstream printstream


    【解决方案1】:

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

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

    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 的结果也将放入您的文件中。

    【讨论】:

    • 我认为应该可以在 java 中将控制台上显示的输出保存到文本文件中......这就是我想要的。
    • @Ronixus 是的 Apache Commons 规则 :)
    • @Anarkie Here 您几乎没有办法将 jars 添加到您的项目中。 “添加外部 JAR”方法 2(您需要打开 Java 视图)或 3 是您要查找的内容:right click on project -> build path -> add external libraries
    • here下载commons-io-2.4-bin.zip。打开包装后,您会看到commons-io-2.4.jar。将其添加到您的项目中。
    • @Anarkie 如果您希望该行也在您的文件中,那么您需要在将标准输出流更改为System.setOut(ps) 后移动打印它的代码。在重定向输出流之前,我看不到任何方法可以包含文件已打印的消息。
    【解决方案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");
            } 
    

    【讨论】:

    • 虽然我认为他想一口气写到两个地方,但我认为这是最接近可行的解决方案。为你 +1。
    • 啊哈,但他没有在他的问题中这么说:)
    【解决方案3】:

    我对这个问题的解决方案是简单地定义你自己的 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);
    }
    

    【讨论】:

      【解决方案4】:

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

      public final static PrintStream out
      

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

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

      System.setOut(ps);
      

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

      【讨论】:

      • 我知道代码有效并且测试...被写入文本文件但测试..循环不在java控制台上,java控制台上打印的文本也不在文本文件中...我想要的是如果我在控制台上打印“Hello 123”,Hello 123 应该在 omt.txt
      • 有没有办法镜像控制台?我觉得java里不应该这么复杂:/
      • mirror console 是什么意思?你想同时打印到控制台和文件吗?
      • 这正是我想要的......如果不能同时做,我希望他们至少显示相同的结果......