在控制台和文本文件中写入内容

12

我从互联网上找到下面的代码,它可以工作,但不会将控制台输出写入omt.txt文件,它只会在第二个catch块后写入System.out.println语句。如果你运行一次代码,你就会理解我的意思。我想做的就是将控制台上的内容写到名为"omt.txt"的文件中,仅此而已...

在得到一些回答之后,我意识到我的问题没有说明清楚,对此我很抱歉。 我想把控制台输出保存到omt.txt文本文件中。如果控制台上打印了"Hello 123",它也应该出现在omt.txt文件中。换句话说,无论控制台上打印了什么,都应该同时写入omt.txt文件,或者在控制台执行后写入,但输出结果应该完全相同!

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个回答

24

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

由于您想在两个流中写入数据,请尝试使用TeeOutputStream,它来自于Apache Commons。将第二个try中的代码更改为:

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中将控制台显示的输出保存到文本文件中应该是可能的...这就是我想要的。 - Anarkie
1
@Ronixus 是的,Apache Commons 好牛逼 :) - Pshemo
1
@Anarkie 在这里(http://www.wikihow.com/Add-JARs-to-Project-Build-Paths-in-Eclipse-%28Java%29)有几种方法可以将jar包添加到您的项目中。 "添加外部JAR"方法2(您需要打开Java视图)或3是您要寻找的:右键单击项目-> 构建路径-> 添加外部库 - Pshemo
1
这里下载commons-io-2.4-bin.zip。解压后,您会看到commons-io-2.4.jar。将其添加到您的项目中。 - Pshemo
1
@Anarkie 如果你想让该行代码也在文件中显示,那么在更改标准输出流为 System.setOut(ps) 后,你需要将打印该行的代码移到后面。在重定向输出流之前,我没有看到包含已经打印出来的消息的任何方法。 - Pshemo
显示剩余10条评论

2
原因是: 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分给你。 - Jops
啊哈,但他在问题中并没有这么说 :) - Alya'a Gamal

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行或在构造函数调用中切换两个printstream的位置)

现在只需定义2个printstream,其中一个将写入您的文件,让我们将其设置为bufferedoutputstream以确保良好的性能:

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

1
System.java 中,这是 out 属性的声明:
public final static PrintStream out

你会发现一次只能有一个PrintSteam对象。所以它要么是控制台,要么是文件,但不能同时存在。
在这行代码中,你已经有效地重新定向了输出目标:
System.setOut(ps);

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

我知道代码是有效的,并且“Testing...”已经被写入文本文件,但是“Testing...”循环没有出现在Java控制台上,Java控制台上打印的文本也没有出现在文本文件中...我的目标是,如果我在控制台上打印“Hello 123”,那么“Hello 123”应该出现在omt.txt文件中。 - Anarkie
有没有一种方法可以镜像控制台?我认为在Java中不应该这么复杂 :/ - Anarkie
什么是“镜像控制台”?你是想同时输出到控制台和文件中吗? - Pshemo
这正是我想要的...如果同时无法实现,我希望它们至少显示相同的结果... - Anarkie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接