我的问题是一个设计问题。我应该使用StringBuilder
并逐行阅读文件,还是应该replace
?
我正在开发一种从文件中读取文本的方法。在文件中可以有@@GOTO:"C:\path\to\more.txt"@@
。我想用@@
的内容替换两个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
而且我可能在这些字符串中有很多信息。
注意它没有坏,我只想问是否有更好的方法。谢谢!
答案 0 :(得分: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,"\"@@","");
答案 1 :(得分:1)
诚实的回答:使用像Freemarker或Velocity这样的现有模板库。
字面答案:Matcher
有两种方法可用于此类情况,appendReplacement()
和appendTail()
。两者都要求你使用StringBuffer,这是不幸的,但它是解决这个问题最优雅的方法。