1.问题来源
项目中有个新需求,需要将某个方法从控制台输出的信息抓取后保存
起来保存到数据库表中或者一个文件中,并且不能影响原先控制台打印信息的展示。因此基于《Java获取控制台输出信息》对实现方法做了进一步优化,以实现以上需求。
这里仍然是两个示例,一个用来将控制台信息保存到数据库表中,另外一个则保存到指定的文件中,并且不影响控制台信息的正常打印。代码如下:
2.打印并获取打印信息
控制台可正常打印信息,并且将打印信息抓取出来进行下一步处理
2.1 自定义打印流工具类
import java.io.OutputStream;
import java.io.PrintStream;
/**
* 继承自 `PrintStream`,可以同时将输出内容发送到两个不同的输出流。
*/
public class TeePrintStream extends PrintStream {
private PrintStream secondStream; // 第二个输出流
/**
* 构造函数,用于创建 `TeePrintStream` 对象。
*
* @param mainStream 主要的输出流
* @param secondStream 第二个输出流
*/
public TeePrintStream(OutputStream mainStream, OutputStream secondStream) {
super(mainStream); // 调用父类 PrintStream 的构造函数,传入主要的输出流
this.secondStream = new PrintStream(secondStream); // 创建第二个输出流
}
/**
* 将字节数组输出到主要和第二个输出流。
*
* @param buf 输出的字节数组
* @param off 数组的起始偏移量
* @param len 要写入的字节数
*/
@Override
public void write(byte[] buf, int off, int len) {
super.write(buf, off, len); // 将字节数组输出到主要输出流
secondStream.write(buf, off, len); // 将字节数组输出到第二个输出流
}
/**
* 刷新主要和第二个输出流。
*/
@Override
public void flush() {
super.flush(); // 刷新主要输出流
secondStream.flush(); // 刷新第二个输出流
}
/**
* 关闭第二个输出流。
*/
@Override
public void close() {
// super.close(); // 务必不要关闭,否则后续正常的标准输出流都无法生效
secondStream.close(); // 关闭第二个输出流
}
}
2.2 实现
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.PrintStream;
import com.qfx.modules.test.bean.TeePrintStream;
/**
* 获取控制台输出信息
*/
/**
* @author user
*
*/
public class ConsoleOutputCaptureDemo {
public static void main(String[] args) {
ConsoleOutput();
ConsoleOutputToFile();
System.out.println("正常输出...");
}
/**
* 控制台输出的同时,获取控制台输出信息放在最后统一处理
*/
public static void ConsoleOutput() {
// 保存原来的标准输出流
PrintStream originalOut = new PrintStream(System.out);
String output = "";
try (ByteArrayOutputStream baos = new ByteArrayOutputStream();
TeePrintStream teePrintStream = new TeePrintStream(System.out, baos)) {
System.setOut(teePrintStream);
for (int i = 1; i <= 5; i++) {
System.out.println(i + ": 这条消息会同时在控制台中显示,并在字节数组输出流中存在");
}
// 获取捕获到的控制台输出
output = baos.toString();
} catch (Exception e) {
e.getMessage();
}
// 恢复原始的标准输出流
System.setOut(originalOut);
System.out.println();
System.out.println("-------------获取抓取到的控制台信息---------------");
System.out.println(output);
}
}
2.3 效果
可以看到正常打印的同时抓取到了控制台打印信息,并重新进行了打印,而且后面的正常输出也没有受到影响
3.打印并保存至文件中
3.1 自定义输出流工具类
import java.io.IOException;
import java.io.OutputStream;
/**
* 输出流的复制工具,它可以将数据同时写入两个不同的输出流中。
*/
public class TeeOutputStream extends OutputStream {
private OutputStream mainStream; // 第一个输出流
private OutputStream outputStream2; // 第二个输出流
/**
* 构造函数,用于创建一个TeeOutputStream对象。
*
* @param mainStream 第一个输出流
* @param outputStream2 第二个输出流
*/
public TeeOutputStream(OutputStream mainStream, OutputStream outputStream2) {
this.mainStream = mainStream;
this.outputStream2 = outputStream2;
}
/**
* 将指定的字节写入输出流中。
*
* @param b 要写入的字节
* @throws IOException 如果发生输入/输出异常
*/
@Override
public void write(int b) throws IOException {
mainStream.write(b);
outputStream2.write(b);
}
/**
* 刷新输出流,确保所有缓冲的数据被写入目标流中。
*
* @throws IOException 如果发生输入/输出异常
*/
@Override
public void flush() throws IOException {
mainStream.flush();
outputStream2.flush();
}
/**
* 关闭输出流,释放任何系统资源。
*
* @throws IOException 如果发生输入/输出异常
*/
@Override
public void close() throws IOException {
// mainStream.close(); // 务必不要关闭,否则后续正常的标准输出流都无法生效
outputStream2.close();
}
}
3.2 实现
import java.io.FileOutputStream;
import java.io.PrintStream;
import com.qfx.modules.test.bean.TeeOutputStream;
/**
* 获取控制台输出信息
*/
public class ConsoleOutputCaptureDemo {
public static void main(String[] args) {
System.out.println();
ConsoleOutputToFile();
System.out.println("正常输出...");
}
/**
* 控制台输出信息的同时输出信息到指定文件中
*/
public static void ConsoleOutputToFile() {
// 保存原来的标准输出流
PrintStream originalOut = new PrintStream(System.out);
try (FileOutputStream fileOutputStream = new FileOutputStream("f:/output.txt");
TeeOutputStream teeOutputStream = new TeeOutputStream(System.out, fileOutputStream);
PrintStream printStream = new PrintStream(teeOutputStream, true, "UTF-8")) {
// 将标准输出流重定向到打印流
System.setOut(printStream);
for (int i = 1; i <= 10; i++) {
System.out.println(i + ": 这条消息会同时在控制台和文件中显示");
Thread.sleep(1000);
}
} catch (Exception e) {
e.printStackTrace();
}
// 恢复原始的标准输出流
System.setOut(originalOut);
}
}
3.3 效果
3.3.1 效果1
控制台打印信息的同时将信息保存到了指定的文件中
3.3.2 效果2
可以看到,执行完
打印并保存至文件中
的操作,恢复了标准的输出流,后续的可以正常打印信息