替换打印流中的文本

时间:2012-07-31 15:05:30

标签: java regex replace printstream

是否可以在打印流中替换正则表达式?

我有一段代码记录了我的控制台窗口中显示的所有文本,但它也记录了ANSI转义码。

我发现这个正则表达式"s:\x1B\[[0-9;]*[mK]::g"可以删除它们,但这只适用于字符串。 有没有办法将正则表达式替换应用于常量字符串流并过滤掉ANSI转义码?

如果可能的话,尽可能地愚弄它,在编程时我仍然是新手,我只是建立在已有的程序上。

修改

我有这个代码,我在堆栈溢出的其他地方找到了,这允许我同时流式传输到日志文件和控制台。

这是我使用的,然后我在此之后设置了开球。

Logging tee = new Logging(file, System.out);

package com.md_5.mc.chat;

import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;

public class Logging extends PrintStream
{
  private final PrintStream second;

  public Logging(OutputStream main, PrintStream second)
  {
    super(main);
    this.second = second;
  }

  public void close()
  {
    super.close();
  }

  public void flush()
  {
    super.flush();
    this.second.flush();
  }

  public void write(byte[] buf, int off, int len)
  {
    super.write(buf, off, len);
    this.second.write(buf, off, len);
  }

  public void write(int b)
  {
    super.write(b);
    this.second.write(b);
  }

  public void write(byte[] b) throws IOException
  {
    super.write(b);
    this.second.write(b);
  }
}

3 个答案:

答案 0 :(得分:1)

您可以在调用相应的super方法之前对相关的打印流进行子类化并执行regexp替换吗? E.g。

public void ExampleStream extends PrintStream {

  @Override
  public void print(String s) {
    super(s.replaceAll(ANSI_PATTERN,""));
  }
}

答案 1 :(得分:1)

创建创建FilterOutputStream的子类,比如说RegexOutputStream。该类应该缓冲写入它的所有数据(来自不同的write(...)方法)。在flush()方法中,它应该应用正则表达式,然后将结果写入基础OutputStream

接下来,实例化PrintWriter以写入RegexOutputStream。这样您就不需要改变PrintWriter类的行为。如果您不再需要过滤,您可以将RegexOutStream从链中取出,一切都会再次运行。

请注意,根据您使用PrintWriter的方式,这可能会导致RegexOutputStream缓冲区变得非常大。如果您创建PrintWriter到autoflush,它将在每行之后和每个字节数组之后刷新。有关详细信息,请参阅其JavaDoc

答案 2 :(得分:0)

我认为Logging类中的代码不是一个好方法(至少是这样):

  • 如果您有权访问PrintStream源代码,您可能会发现当前重新定义的方法可能根本没有被使用:PrintStream #print(...)方法委托textOut#write(...)(不是重新定义的OutputStream#write(...))。
  • 因此,您应该重新定义print(String)和print(char [])方法,以便有效地过滤输出。
  • 答案中有一些重新定义的方法示例(包括进一步说明这一点)。

或者,如果你只是想要一个过滤掉ANSI代码的PrintStream(正如我最初所理解的那样),那么在FilterOutputStream上实现它会更方便(正如mthmulders建议的那样,因为你将不得不重新定义更少的东西和将更容易重复使用):

  • 制作BufferedOutputStream课程的副本。根据您的喜好命名。 (例如 TrimAnsiBufferedStream
  • 然后重新定义de flushBuffer()方法:

    private void flushBuffer() throws IOException {
        if (count > 0) {
            String s = new String(buf, 0, count); // Uses system encoding.
            s.replaceAll(ANSI_PATTERN, "");
            out.write(s.getBytes());
            count = 0;
        }
    }
    
  • 当您需要实例化替换ANSI的PrintStream时,请调用new PrintStream(new TrimAnsiBufferedStream(nestedStream))

  • 这可能不是防弹(例如编码配置可能发生的任何情况,或者缓冲区大小不够大,或者打印流中的刷新选项),但我不会过度复杂化。
顺便说一下。欢迎kukelekuuk00。请务必阅读常见问题和答案的反馈(我们关心您,请回复)。