最近在回頭看Java IO的源碼,就想着可不可以用java實現一個替換文件中字符串的方法,就像Linux的sed命令那樣。在決定做之前,先到網上找了一些資料,可是發現大多數的實現都是把文件的全部內容都load到內存里面,然后調用String的字符替換方法。感覺很不靠譜就是了。於是就動手寫了下面這個小demo。
Java的輸入輸出流做不到隨機存取,因此實現的時候,就把替換過字符串的文件輸出到了另一個文件里面了(嚴格來講,不是替換字符串,而是替換匹配到的字節)。如果要對同一個文件做替換,同學們可以也許用RandomAccessFile,而不是Java 流。
實現類有個緩存buf,內存里面最多存放buf.length個字節,以進行替換操作,因此在把原字符串替換成新字符串的時候,原字符串的長度不能超過buf.length。
直接上代碼:
public class MyFileModifier {
private MyFileReader reader = null;
private MyFileWriter writer = null;
private byte[] buf = null;
private static final int DEFAULT_BUFFER_SIZE = 8192;
private static int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
public MyFileModifier(String path,String newFilePath) throws FileNotFoundException {
// 默認的輸入輸出流形式
this.reader = new MyFileReader(new FileInputStream(path));
this.writer = new MyFileWriter(new FileOutputStream(newFilePath,true));
buf = new byte[DEFAULT_BUFFER_SIZE];
}
public MyFileModifier(String path,String newFilePath,int bufSize) throws FileNotFoundException {
// 默認的輸入輸出流形式
this.reader = new MyFileReader(new BufferedInputStream(new FileInputStream(path)));
this.writer = new MyFileWriter(new BufferedOutputStream(new FileOutputStream(newFilePath)));
buf = new byte[Math.min(MAX_BUFFER_SIZE,bufSize)];
}
//將文件中所有匹配到的字節替換
public int replaceAll(byte[] content,byte[] newContent) throws IOException {
int cLength = content.length;
if(cLength > buf.length){
throw new IndexOutOfBoundsException("Content too large!");
}
if(reader.available()<=0){
return 0;
}
byte[] buf0 = new byte[cLength-1];
int replaceCount = 0;
int rc = reader.read(buf);
while(true) {
int i;
for(i = 0;i<rc-cLength+1;i++) {
int matchLength = 0;
for (int m = 0; m < cLength; m++) {
if (buf[i+m] != content[m]) {
break;
}
matchLength ++;
}
if(matchLength == cLength){
writer.write(newContent);
i += cLength-1;
replaceCount ++ ;
continue;
}
writer.write(buf[i]);
}
writer.flush();
if(reader.available()>0) {
System.arraycopy(buf, i, buf0, 0, rc-i);
System.arraycopy(buf0, 0, buf, 0, rc-i);
rc = reader.read(buf,rc-i,buf.length-rc+i) + rc - i;
}else {
for(;i<rc;i++){
writer.write(buf[i]);
}
writer.flush();
break;
}
}
return replaceCount;
}
public static void main(String args[]) throws FileNotFoundException {
MyFileModifier myFileModifier = new MyFileModifier("test.properties","myfile.txt",10);
if(myFileModifier == null){
System.out.println("文件未找到");
System.exit(1);
}
try {
int c = myFileModifier.replaceAll(new String("行").getBytes("UTF-8"),new String("哈哈哈哈").getBytes("UTF-8"));
System.out.println(c);
} catch (IOException e) {
e.printStackTrace();
}
}
}
如果有疑問或建議,歡迎大家與我交流。
