代码之家  ›  专栏  ›  技术社区  ›  flybywire

Java:一个流中的搜索和替换

  •  3
  • flybywire  · 技术社区  · 15 年前

    如何在Java流(输入或输出)中进行即时搜索和替换?

    我不想将流加载到内存或文件中。

    我只是看到了经过的字节,我需要做一些替换。被替换的序列很短(最多20个字节)。

    3 回复  |  直到 12 年前
        1
  •  4
  •   denis.zhdanov    15 年前

    您可以使用提供的类 here 如果静态替换规则对您足够。

        2
  •  1
  •   Lucero    15 年前

    您可以实现 deterministic finite automaton 它只查看每个字节一次(例如,不需要查找),这样基本上您就可以通过一个缓冲区来传输输入,缓冲区的字符数与模式的长度相同,在模式前进时将模式输出到匹配或溢出(不匹配)的字符上。准备好模式后,运行时间是线性的。

    维基百科有一些关于 pattern matching and how that works 理论上。

        3
  •  0
  •   Ben    12 年前

    我从提供的链接中得到了一些好主意,最后编写了一个小类来处理流中$var$变量的替换。对于子孙后代:

    public class ReplacingOutputStream extends OutputStream {
        private static final int DOLLAR_SIGN = "$".codePointAt(0);
        private static final int BACKSLASH = "\\".codePointAt(0);
        private final OutputStream delegate;
        private final Map<String, Object> replacementValues;
    
        private int previous = Integer.MIN_VALUE;
        private boolean replacing = false;
        private ArrayList<Integer> replacement = new ArrayList<Integer>();
    
    
        public ReplacingOutputStream(OutputStream delegate, Map<String, Object> replacementValues) {
            this.delegate = delegate;
            this.replacementValues = replacementValues;
        }
    
        public @Override void write(int b) throws IOException {
            if (b == DOLLAR_SIGN && previous != BACKSLASH) {
                if (replacing) {
                    doReplacement();
                    replacing = false;
                } else {
                    replacing = true;
                }
            } else {
                if (replacing) {
                    replacement.add(b);
                } else {
                    delegate.write(b);
                }
            }
    
            previous = b;
        }
    
        private void doReplacement() throws IOException {
            StringBuilder sb = new StringBuilder();
            for (Integer intval : replacement) {
                sb.append(Character.toChars(intval));
            }
            replacement.clear();
    
            String oldValue = sb.toString();
            Object _newValue = replacementValues.get(oldValue);
            if (_newValue == null) {
                throw new RuntimeException("Could not find replacement variable for value '"+oldValue+"'.");
            }
    
            String newValue = _newValue.toString();
            for (int i=0; i < newValue.length(); ++i) {
                int value = newValue.codePointAt(i);
                delegate.write(value);
            }
        }
    }