Java – 捕获System.err.println或捕获PrintStream

Java新手问题:

我需要捕获第三方组件正在写入printStream的文本。

PrintStream默认为System.err,但可以更改为另一个PrintStream。

浏览文档,我找不到一种简单的方法将PrintStream的内容定向到字符串编写器/缓冲区。

有人可以帮忙吗?

PipedOutputStream pipeOut = new PipedOutputStream(); PipedInputStream pipeIn = new PipedInputStream(pipeOut); System.setOut(new PrintStream(pipeOut)); // now read from pipeIn 
 import java.io.*; public class Test { public static void main(String[] args) { FileOutputStream fos = null; try { fos = new FileOutputStream("errors.txt"); } catch(IOException ioe) { System.err.println("redirection not possible: "+ioe); System.exit(-1); } PrintStream ps = new PrintStream(fos); System.setErr(ps); System.err.println("goes into file"); } } 

您可以围绕任何其他OutputStream创建PrintStream。

创建一个转到内存缓冲区的最简单方法是:

 PrintStream p = new PrintStream( new ByteArrayOutputStream() ) 

然后,您可以在任何您喜欢的点读取和重置字节数组的内容。

另一种可能性是使用管道。

 InputStream third_party_output = new PipedInputStream(); PrintStream p = new PrintStream( new PipedOutputStream( third_party_output ) ); 

然后,您可以从third_party_output流中读取以获取库写入的文本。

你在找这样的东西吗?

  OutputStream redirect = System.err; PrintStream myPrintStream = new PrintStream(redirect); myPrintStream.println("hello redirect"); 

如果您可以将myPrintStream传递给第三方应用程序,则可以将其重定向到任何您想要的位置。

我使用以下类将System.out和System.err记录到一组旋转文件(其中xxx-001.log是最新的)。 它包含一些对实用程序方法的调用,在编译之前需要先实现它们 – 它们应该是不言自明的。

 import java.io.*; import java.lang.reflect.*; public class LoggerOutputStream extends OutputStream { // ***************************************************************************** // INSTANCE PROPERTIES // ***************************************************************************** private FileOutputStream log=null; // the base output stream private String fnmBase,fnmExt; // filename base, file extension private int fnmCount,fnmLast; // count for filename index, last filename used private int logSize,totWritten; // max log size, current number of bytes written // ***************************************************************************** // INSTANCE CONSTRUCTORS/INIT/CLOSE/FINALIZE // ***************************************************************************** public LoggerOutputStream(String baseFilename) throws IOException { this(baseFilename,".log",2,1024000); } public LoggerOutputStream(String baseFilename, String extension) throws IOException { this(baseFilename,extension,2,1024000); } public LoggerOutputStream(String baseFilename, String extension, int numberOfFiles, int maxFileSize) throws IOException { fnmBase=baseFilename; if(Character.isLetterOrDigit(fnmBase.charAt(fnmBase.length()-1))) { fnmBase=(fnmBase+"-"); } fnmExt=extension; if(!fnmExt.startsWith(".")) { fnmExt=('.'+fnmExt); } fnmCount=numberOfFiles; logSize=maxFileSize; if(fnmCount>MAXLOGS) { fnmCount=MAXLOGS; } fnmLast=0; for(int xa=1; xa<=MAXLOGS; xa++) { if(!new File(constructFilename(xa)).exists()) { while((--xa)>fnmCount) { IoUtil.deleteFile(constructFilename(xa)); } fnmLast=xa; break; } } log=null; openFile(false); if(numberOfFiles>MAXLOGS) { System.out.println("** Log File Count Limited To "+MAXLOGS); } } public void close() throws IOException { close(false); } private void openFile(boolean ovrflw) throws IOException { close(true); if (fnmLast< fnmCount) { fnmLast++; } else if(fnmLast==fnmCount) { IoUtil.deleteFile(constructFilename(fnmCount)); } for(int xa=fnmLast; xa>0; xa--) { IoUtil.renameFile(constructFilename(xa-1),constructFilename(xa)); } log=new FileOutputStream(constructFilename(1)); totWritten=0; } private String constructFilename(int index) { return constructFilename(fnmBase,index,fnmExt); } private synchronized void close(boolean ovrflw) throws IOException { if(log!=null) { log.flush(); log.close(); log=null; } } // ***************************************************************************** // INSTANCE METHODS - ACCESSORS // ***************************************************************************** public String getFilename() { return constructFilename(1); } public String getFilename(int idx) { return constructFilename(idx); } public synchronized void cycleLogFile() throws IOException { openFile(true); } // ***************************************************************************** // INSTANCE METHODS // ***************************************************************************** public synchronized void flush() throws IOException { if(log!=null) { log.flush(); } } public synchronized void write(int val) throws IOException { if(log!=null) { log.write(val); totWritten++; if(val=='\n') { if(totWritten>logSize) { openFile(true); } else { log.flush(); } } } } public synchronized void write(byte[] bytes) throws IOException { if(log!=null) { log.write(bytes); totWritten+=bytes.length; if(bytes.length>0 && bytes[bytes.length-1]=='\n') { if(totWritten>logSize) { openFile(true); } else { log.flush(); } } } } public synchronized void write(byte[] bytes, int str, int len) throws IOException { if(log!=null) { log.write(bytes,str,len); totWritten+=len; if(bytes.length>(str+len-1) && bytes[str+len-1]=='\n') { if(totWritten>logSize) { openFile(true); } else { log.flush(); } } } } // ***************************************************************************** // STATIC PROPERTIES // ***************************************************************************** static public final int MAXLOGS=999; // maximum log files allowed // ***************************************************************************** // STATIC METHODS // ***************************************************************************** static public String constructFilename(String bas, int idx, String ext) { if(!bas.endsWith("-") && !bas.endsWith("_") && !bas.endsWith(".")) { bas=(bas+"-"); } if(!ext.startsWith(".") ) { ext=('.'+ext); } return (bas+TextUtil.raZeros(idx,3)+ext); } } /* END PUBLIC CLASS */