用Java IO流替换文件中的字符串

时间:2023-02-09 09:00:05

 

  最近在回头看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();
        }
    }
}
  

  如果有疑问或建议,欢迎大家与我交流。