1

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

我有一段代码记录了控制台窗口中显示的所有文本,但它也记录了 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);
  }
}
4

3 回答 3

1

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

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

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

于 2012-07-31T15:18:36.730 回答
1

您可以对有问题的打印流进行子类化并在调用适当的方法之前执行您的正则表达式替换super?例如

public void ExampleStream extends PrintStream {

  @Override
  public void print(String s) {
    super(s.replaceAll(ANSI_PATTERN,""));
  }
}
于 2012-07-31T15:08:35.580 回答
0

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

  • 如果您有权访问 PrintStream 源代码,您可能会发现当前重新定义的方法可能根本没有使用: PrintStream#print(...) 方法委托于 textOut#write(...) (不在重新定义的 OutputStream 上) #写(...) )。
  • 因此,您应该重新定义 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。请务必阅读常见问题解答和对答案的反馈(我们关心您,请回报)。

于 2012-07-31T16:25:03.923 回答