Domanda

Come faccio a cercare al volo & amp; sostituire in un flusso Java (input o output)?

Non voglio caricare il flusso in memoria o in un file.

Vedo solo i byte che passano e devo fare alcune sostituzioni. Le sequenze da sostituire sono brevi (fino a 20 byte).

È stato utile?

Soluzione

Puoi utilizzare la classe fornita qui se le regole di sostituzione statica sono sufficienti per te.

Altri suggerimenti

Potresti implementare un automa deterministico finito che guarda ogni byte una volta sola (es. no lookbehind è necessario), in modo da poter fondamentalmente trasmettere l'input attraverso un buffer contenente al massimo un numero di caratteri pari alla lunghezza del pattern, producendo il pattern su una corrispondenza o caratteri traboccanti (non corrispondenti) quando avanzi nel pattern. Il runtime è lineare dopo la preparazione del pattern.

Wikipedia ha alcune informazioni su corrispondenza dei modelli e su come funziona in teoria.

Ho ricevuto alcune buone idee dal link fornito e ho finito per scrivere una piccola classe per gestire la sostituzione di variabili $ VAR $ in uno stream. Per i posteri:

public class ReplacingOutputStream extends OutputStream {
    private static final int DOLLAR_SIGN = "<*>quot;.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);
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top