简体   繁体   English

Java 流是否有一个简单的“tee”过滤器?

[英]Is there a simple “tee” filter for Java streams?

For debugging purpouses I would like to dump the content of an output stream into a file while it is processed.为了调试目的,我想在处理输出流时将其内容转储到文件中。 The stream is parsed by org.xml.sax.XMLReader which will comsume the data.该流由org.xml.sax.XMLReader解析,它将消耗数据。

I would gess one need a filter to archive this and before writing one my self I wanted to ask if there is a ready made version allready.我认为需要一个过滤器来存档这个,在我自己写一个之前,我想问一下是否有一个现成的版本。

UPDATE:更新:

Should habe mentioned that I work on Android.应该提到我在Android上工作。

What Do I have:我有什么:

        final org.apache.http.HttpEntity responseEntity = response.getEntity ();
        final java.io.InputStream content = responseEntity.getContent ();
        final java.io.InputStreamReader contentReader =
           new java.io.InputStreamReader (content, "UTF-8");

So I have an java.io.InputStream and an InputStreamReader .所以我有一个java.io.InputStream和一个InputStreamReader

Commons IO to the rescue!公共 IO来救援! Check out TeeInputStream and TeeOutputStream .查看TeeInputStreamTeeOutputStream

Not quite a ready rolled one, but this might be of interest.并不完全是准备推出一个,但是可能会感兴趣。 There is a TeeOutputStream implementation in the examples.示例中有一个TeeOutputStream实现。

Thanks for all the pointer.谢谢大家指点。 Here a copy of the class I created to solve my problem:这是我为解决问题而创建的类的副本:

/**
 * <p>
 * Tee-Filters a Reader into an Writer.
 * </p>
 * 
 * @author "Martin Krischik" <martin.krischik@noser.com>
 * @version 1.0 $Revision: 1046 $
 * @since 1.0
 */
public class TeeReader
   extends
      java.io.Reader
{
   /**
    * <p>
    * Reader to read from
    * </p>
    */
   private final java.io.Reader in;
   /**
    * <p>
    * Tee output to which read date is written before beeing passed on.
    * </p>
    */
   private final java.io.Writer tee;

   /**
    * <p>
    * create new filter.
    * </p>
    * 
    * @param in
    *           Reader to read from
    * @param tee
    *           Tee output to which read date is written before beeing passed
    *           on.
    */
   public TeeReader (final java.io.Reader in, final java.io.Writer tee)
   {
      this.in = in;
      this.tee = tee;
   } // TeeReader

   /**
    * <p>
    * Close the stream. Once a stream has been closed, further read(), ready(),
    * mark(), or reset() invocations will throw an IOException. Closing a
    * previously-closed stream, however, has no effect.
    * </p>
    * 
    * @throws java.io.IOException
    * @see java.io.Reader#close()
    */
   @Override
   public void close ()
      throws java.io.IOException
   {
      this.in.close ();
   } // close

   /**
    * <p>
    * Reads characters into a portion of an array. This method will block until
    * some input is available, an I/O error occurs, or the end of the stream is
    * reached.
    * </p>
    * 
    * @param cbuf
    *           Destination buffer
    * @param off
    *           Offset at which to start storing characters
    * @param len
    *           Maximum number of characters to read
    * @return The number of characters read, or -1 if the end of the stream has
    *         been reached Throws:
    * @throws java.io.IOException
    * @see java.io.Reader#read(char[], int, int)
    */
   @Override
   public int read (final char [] cbuf, final int off, final int len)
      throws java.io.IOException
   {
      final int retval = this.in.read (cbuf, off, len);

      if (retval >= 0)
      {
         this.tee.write (cbuf, off, len);
      }
      else
      {
         this.tee.close ();
      } // if

      return retval;
   } // read
} // TeeReader

Here's a trivial output stream version (without exception handling):这是一个简单的输出流版本(没有异常处理):

   public class TeeOutputStream extends OutputStream
   {
           private OutputStream[] streams;

           public TeeOutputStream(final OutputStream ... streams)
           {
                   this.streams = streams;
           }

           @Override
           public void close() throws IOException
           {
                   for (OutputStream stream : streams)
                   {
                           stream.close();
                   }
           }

           @Override
           public void flush() throws IOException
           {
                   for (OutputStream stream : streams)
                   {
                           stream.flush();
                   }

           }

           @Override
           public void write(final byte[] buffer) throws IOException
           {
                   for (OutputStream stream : streams)
                   {
                           stream.write(buffer);
                   }

           }

           @Override
           public void write(final byte[] buffer, final int offset, final int count) throws IOException
           {
                   for (OutputStream stream : streams)
                   {
                           stream.write(buffer, offset, count);
                   }

           }

           @Override
           public void write(final int i) throws IOException
           {
                   for (OutputStream stream : streams)
                   {
                           stream.write(i);
                   }
           }
   }

I had the same problem.我有同样的问题。 I wanted to be able to see what the Xml parser is getting so I could debug the server-side scripts.我希望能够看到 Xml 解析器得到了什么,以便我可以调试服务器端脚本。 Ideally, you want to send the Xml to both the Xml parser and LogCat.理想情况下,您希望将 Xml 发送到 Xml 解析器和 LogCat。 You can use the enclosed clss InputStreamIntercept to do that.您可以使用封闭的 clss InputStreamIntercept 来做到这一点。 Just run the input stream through it:只需通过它运行输入流:

final java.io.InputStream content = 
          new InputStreamIntercept(responseEntity.getContent());

Here is the class:这是课程:

import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;

import android.util.Log;

/**
 * This custom stream filter can intercept data being
 * sent to another stream and send it to LogCat. It is 
 * useful as a way to tell what is being sent to an
 * Xml parser.
 */
public class InputStreamIntercept extends FilterInputStream {

    /**
     * The string we build from data we input.
     */
    private StringBuilder sb = new StringBuilder();

    /**
     * Constructor.
     * @param in the stream we are intercepting
     */
    public InputStreamIntercept(InputStream in) {
        super(in);
    }

    /**
     * Intercept read() and store the character for output
     * @returns -1 if nothing read or the character read
     */
    @Override
    public int read() throws IOException {
        int ret = super.read();
        if(ret >= 0) {
            newChar((byte)ret);
        }
        return ret;
    }

    /**
     * Intercept read and output the content to Log.i.
     */
    @Override
    public int read(byte[] buffer, int offset, int count) throws IOException {
        int ret = super.read(buffer, offset, count);
        for(int i=0;  i<ret;  i++) {
            newChar(buffer[i]);
        }
        return ret;
    }


    /**
     * Handle a new character. We output whenever we get a newline
     * @param ch
     */
    private void newChar(byte ch) {
        if(ch == 10) {
            String str = sb.toString();
            if(str.equals("")) {
                Log.i("debug", "--blank line--");
            } else {
                Log.i("debug", str);
            }

            sb = new StringBuilder();
        } else if(ch == 13) {
            // Skip this character
        } else {
            sb.append((char)ch);
        }
    }

    /**
     * Close the stream
     */
    @Override
    public void close() throws IOException {
        super.close();
        if(sb.length() > 0) {
            Log.i("debug", sb.toString());
        }
    }

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM