【问题标题】:Removing ASCII characters in a string with encoding使用编码删除字符串中的 ASCII 字符
【发布时间】:2014-07-16 05:03:47
【问题描述】:

我有一个由串行端口事件填充的字节数组,代码如下所示:

private InputStream input = null; 
......
......
public void SerialEvent(SerialEvent se){
  if(se.getEventType == SerialPortEvent.DATA_AVAILABLE){
    int length = input.available();
    if(length > 0){
      byte[] array = new byte[length];
      int numBytes = input.read(array);
      String text = new String(array);
    }
  }
}

变量text 包含以下字符,

"\033[K", "\033[m",  "\033[H2J", "\033[6;1H" ,"\033[?12l", "\033[?25h", "\033[5i", "\033[4i", "\033i" and similar types..

到目前为止,我使用String.replace 从字符串中删除所有这些字符。

我尝试过new String(array , 'CharSet'); //Tried with all CharSet options,但无法删除它们。

有什么方法可以在不使用替换方法的情况下删除这些字符?

【问题讨论】:

  • 你确定你从这个端口收到的内容是基于文本的吗?
  • @Oleg Estekhin 我得到 [SquareSymbol] ,它是转义序列 \033 后跟我显示的任何内容。例如 [Square][k 这样的。
  • input.available() 不是检查输入流中实际可用字节数的可靠方法,您应该使用InputStream.read(byte[],int,int) 上的正确循环替换该部分代码,否则您正在阅读不完整随机长度的数据块。
  • 另外,input.read(array) 不能保证读取完整的数组,因此您当前的代码首先无法确定流中真正可用的字节数,然后甚至无法读取错误确定的数量字节数。
  • @OlegEstekhin input.read(array, ?, ?) 你能给我一个小例子吗.. 或者一个链接开始。

标签: java string character-encoding ascii


【解决方案1】:

我给出了一个不满意的答案,感谢@OlegEstekhin 指出这一点。 还没有其他人回答,而且解决方案不是两条线,就这样吧。

制作一个丢弃转义序列的包装 InputStream。我使用了 PushbackInputStream,其中跳过了部分序列,可能仍会被推回以首先读取。这里FilterInputStream 就足够了。

public class EscapeRemovingInputStream extends PushbackInputStream {

    public static void main(String[] args) {
        String s = "\u001B[kHello \u001B[H12JWorld!";
        byte[] buf = s.getBytes(StandardCharsets.ISO_8859_1);
        ByteArrayInputStream bais = new ByteArrayInputStream(buf);
        EscapeRemovingInputStream bin = new EscapeRemovingInputStream(bais);
        try (InputStreamReader in = new InputStreamReader(bin,
                StandardCharsets.ISO_8859_1)) {
            int c;
            while ((c = in.read()) != -1) {
                System.out.print((char) c);
            }
            System.out.println();
        } catch (IOException ex) {
            Logger.getLogger(EscapeRemovingInputStream.class.getName()).log(
                Level.SEVERE, null, ex);
        }
    }

    private static final Pattern ESCAPE_PATTERN = Pattern.compile(
        "\u001B\\[(k|m|H\\d+J|\\d+:\\d+H|\\?\\d+\\w|\\d*i)");
    private static final int MAX_ESCAPE_LENGTH = 20;

    private final byte[] escapeSequence = new byte[MAX_ESCAPE_LENGTH];
    private int escapeLength = 0;
    private boolean eof = false;

    public EscapeRemovingInputStream(InputStream in) {
        this(in, MAX_ESCAPE_LENGTH);
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        for (int i = 0; i < len; ++i) {
            int c = read();
            if (c == -1) {
                return i == 0 ? -1 : i;
            }
            b[off + i] = (byte) c;
        }
        return len;
    }

    @Override
    public int read() throws IOException {
        int c = eof ? -1 : super.read();
        if (c == -1) { // Throw away a trailing half escape sequence.
            eof = true;
            return c;
        }
        if (escapeLength == 0 && c != 0x1B) {
            return c;
        } else {
            escapeSequence[escapeLength] = (byte) c;
            ++escapeLength;
            String esc = new String(escapeSequence, 0, escapeLength,
                    StandardCharsets.ISO_8859_1);
            if (ESCAPE_PATTERN.matcher(esc).matches()) {
                escapeLength = 0;
            } else if (escapeLength == MAX_ESCAPE_LENGTH) {
                escapeLength = 0;
                unread(escapeSequence);
                return super.read(); // No longer registering the escape
            }
            return read();
        }
    }

}
  • 用户致电EscapeRemovingInputStream.read
  • 这个read 可能会调用一些读取本身来填充字节缓冲区逃逸序列
  • (可以致电unread 进行回推)
  • 原来的read返回。

转义序列的识别似乎符合语法:命令字母、数字参数。因此我使用正则表达式。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-14
    • 1970-01-01
    • 2014-01-07
    • 1970-01-01
    • 2023-03-18
    相关资源
    最近更新 更多