最近在回头看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(); } } }
如果有疑问或建议,欢迎大家与我交流。