1

私の質問はデザインの質問です。を使用しStringBuilderてファイルを 1 行ずつ読み取る必要がありreplaceますか?

ファイルからテキストを読み取る方法を開発しています。ファイル内には、@@GOTO:"C:\path\to\more.txt"@@. @@2 つの の間のすべてを の内容に置き換えたいC:\path\to\more.txt。また、その中more.txtに別の@@GOTO:"C:\path\to\evenmore.txt"@@. したがって、これを再帰的に行うのが最善だと思います。

私はこのようなことを考えています:

private String replaceGoTo(Pattern pattern, String xmlString) throws IOException {
  Matcher match = pattern.matcher(xmlString);
  while (match.find()) {
    String replacText = IOHelper.fileToString(match.group(2));
    String insert = replaceGoTo(pattern, replacText);
    xmlString = xmlString.replace(match.group(1), insert);
  }
  return xmlString;
}

StringBuilderしかし、私は aを使用しておらず、これらの文字列に多くの情報が含まれている可能性があるため、それが最も効果的な方法であるかどうか疑問に思います。

壊れているわけではありません。もっと良い方法があるかどうかを尋ねているだけです。ありがとう!

4

2 に答える 2

2

最も効率的な方法は、ファイルの読み取り中に開始文字列と終了文字列を置き換える FilterReader を作成することです。静的データを正規表現で置き換える必要はないと思います。次のコードはトリックを行うことができます:

public class ReplaceFilterReader extends Reader {
    private String match;
    private String replace;

    private BufferedReader in;
    private boolean matched;
    private int currentPos;
    private boolean end = false;

    public ReplaceFilterReader(Reader in, String match, String replace) {
        this.in = new BufferedReader(in);
        this.matched = false;
        this.currentPos = 0;
        this.match = match;
        this.replace = replace;
    }

    @Override
    public int read(CharBuffer target) throws IOException {
        int len = target.remaining();
        char[] cbuf = new char[len];
        int n = read(cbuf, 0, len);
        if (n > 0) {
            target.put(cbuf, 0, n);
        }
        return n;
    }

    @Override
    public int read(char[] cbuf) throws IOException {
        return this.read(cbuf, 0, cbuf.length);
    }

    @Override
    public int read() throws IOException {
        char cb[] = new char[1];
        if (this.read(cb, 0, 1) == -1) {
            return -1;
        } else {
            return cb[0];
        }
    }

    private int readNext() throws IOException {
        int result = 0;
        if (!matched) {
            this.in.mark(match.length());
            char cb[] = new char[match.length()];
            int n = this.in.read(cb);
            if (n>0) {
                String s = new String(cb);
                if (s.equals(match)) {
                    this.matched = true;
                    if (replace.length()>0) {
                        result = replace.charAt(currentPos);
                        currentPos+=1;
                        if (currentPos == replace.length()) {
                            this.matched = false;
                            this.currentPos = 0;
                        }
                    } else {
                        this.matched = false;
                        this.currentPos = 0;
                        result = 0;
                    }

                } else {
                    this.in.reset();
                    result = this.in.read();
                }
            } else {
                result = n;
            }
        } else {
            result = replace.charAt(currentPos);
            currentPos+=1;
            if (currentPos == replace.length()) {
                this.matched = false;
                this.currentPos = 0;
            }
        }

        return result;
    }

    @Override
    public int read(char[] cbuf, int off, int len) throws IOException {
        if (end) {
            return -1;
        }

        int n = 0;
        int read = 0;
        for (int i=0; i<len && n!=-1; i++) {
            n = this.readNext();
            if (n!=-1 && n!=0) {
                read += 1;
                cbuf[off+i] = (char) n;
            } else if (n==0) {
                i = i-1;
            }
        }

        if (n == -1) {
            end = true;
        }

        return read;
    }

    @Override
    public void close() throws IOException {
        this.in.close();
    }
}

そして、次のように進めます。

Reader yourReader = // open file ...
Reader replaceStart = new ReplaceFilterReader(yourReader,"@@GOTO:\"","");
Reader replaceEnd = new ReplaceFilterReader(replaceStart,"\"@@","");
于 2012-06-18T14:16:01.920 に答える
1

正直な答え: Freemarker や Velocity などの既存のテンプレート ライブラリを使用します。

文字通りの答え:Matcherこの種の状況に役立つ 2 つの方法がappendReplacement()ありappendTail()ます。どちらも StringBuffer を使用する必要がありますが、これは残念なことですが、このような問題を解決する最も洗練された方法です。

于 2012-06-18T14:16:53.717 に答える