【问题记录】在一个文件中匹配字符出现的次数

在一个文件中找出某段字符出现的次数

今天突发奇想,想到了这个问题,如题

我在网上搜到了两种答案,我先贴出来大家看下有什么问题:

第一种:读取每行去匹配

/**
     * 统计给定文件中给定字符串的出现次数
     * 
     * @param filename  文件名
     * @param word 字符串
     * @return 字符串在文件中出现的次数
     */
    public static int countWordInFile(String filename, String word) {
        int counter = 0;
        try (FileReader fr = new FileReader(filename)) {
            try (BufferedReader br = new BufferedReader(fr)) {
                String line = null;
                while ((line = br.readLine()) != null) {
                    int index = -1;
                    while (line.length() >= word.length() && (index = line.indexOf(word)) >= 0) {
                        counter++;
                        line = line.substring(index + word.length());
                    }
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return counter;
    }

第二种:所有字符存入StringBuilder后再去匹配

public static int count(String filename, String target)
            throws FileNotFoundException, IOException {
        FileReader fr = new FileReader(filename);
        BufferedReader br = new BufferedReader(fr);
        StringBuilder strb = new StringBuilder();
        while (true) {
            String line = br.readLine();
            if (line == null) {
                break;
            }
            strb.append(line);
        }
        String result = strb.toString();
        int count = 0;
        int index = 0;
        while (true) {
            index = result.indexOf(target, index + 1);
            if (index > 0) {
                count++;
            } else {
                break;
            }
        }
        br.close();
        return count;
    } 

大家想一下各有什么问题?

第一种:问题在于如果所匹配的字符正好位于两行换行处
第二种:问题在于如果只是小文件倒不会出现什么问题,但是如果文件大小是百M千M,那势必会引起OOM

我先贴出来我的解决办法,在说明下思路:

public static int countWordInFile(String filename, String word) {
        FileReader fileReader;
        BufferedReader bufferedReader;
        int count = 0;
        try {
            fileReader = new FileReader(filename);
            bufferedReader = new BufferedReader(fileReader);
            String currentLineStr = bufferedReader.readLine();
            String nextLineStr;
            while (currentLineStr != null) {
                nextLineStr = bufferedReader.readLine();
                //当前是最后一行
                if (nextLineStr == null) {
                    count += getContainCounts(currentLineStr, word);
                    break;
                }
                //下一行字符长度小于word.length()(注意不一定是最后一行)
                if (nextLineStr.length() < word.length()) {
                    currentLineStr += nextLineStr;
                    count += getContainCounts(currentLineStr, word);
                    currentLineStr = bufferedReader.readLine();
                } else {
                    //计算两次不同值
                    int currentCount = getContainCounts(currentLineStr, word);
                    currentLineStr += nextLineStr.substring(0, word.length() - 1);
                    int currentAddNextCount = getContainCounts(currentLineStr, word);
                    //记录出现次数
                    count += currentAddNextCount;
                    if (currentCount == currentAddNextCount) {
                        currentLineStr = nextLineStr;
                    } else {
                        currentLineStr = nextLineStr.substring(word.length() - 1, nextLineStr.length());
                    }
                }

            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return count;
    }

1:首先判断是不是最后一行,如果是直接结束循环
2:判断下一行的长度是否>=匹配字符的长度,如果小于的话说明下一行不可能匹配到该字符,直接把该行的字符全部加到当前字符上去匹配,如果大于等于的话,这时候会有两种情况:第一,当前行+下一行匹配到的数量=当前行匹配到的数量,也就是说加不加下一行不影响;第二,当前行+下一行匹配到的数量>当前行单独匹配的数量,也就是说匹配字符恰巧处在两行的首位;对于第一种情况,下次匹配时可以使用整行去匹配,对于第二种,下次匹配的时候必须-上次所用掉的一部分;

解决办法如下:

/**
     * 统计给定文件中给定字符串的出现次数
     * @param filename 文件名
     * @param word     字符串
     * @return 字符串在文件中出现的次数
     */
    public static int countWordInFile(String filename, String word) {
        FileReader fileReader;
        BufferedReader bufferedReader;
        int count = 0;
        try {
            fileReader = new FileReader(filename);
            bufferedReader = new BufferedReader(fileReader);
            String currentLineStr = bufferedReader.readLine();
            String nextLineStr;
            while (currentLineStr != null) {
                nextLineStr = bufferedReader.readLine();
                //当前是最后一行
                if (nextLineStr == null) {
                    count += getContainCounts(currentLineStr, word).first;
                    break;
                }
                //下一行字符长度小于word.length()(注意不一定是最后一行)
                if (nextLineStr.length() < word.length()) {
                    currentLineStr += nextLineStr;
                    count += getContainCounts(currentLineStr, word).first;
                    currentLineStr = bufferedReader.readLine();
                } else {
                    Pair<Integer, Integer> pair = getContainCounts(currentLineStr, word);
                    //计算两次不同值
                    int currentCount = pair.first;
                    currentLineStr += nextLineStr.substring(0, word.length() - 1);
                    pair = getContainCounts(currentLineStr, word);
                    int currentAddNextCount = pair.first;
                    //记录出现次数
                    count += currentAddNextCount;
                    if (currentCount == currentAddNextCount) {
                        currentLineStr = nextLineStr;
                    } else {
                        //不可使用lastIndexOf(word) 原因大家可以自己思考下
                        int useCount = pair.second - (currentLineStr.length() - word.length() + 1);
                        currentLineStr = nextLineStr.substring(useCount, nextLineStr.length());
                    }
                }

            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return count;
    }

获得匹配数量方法

/**
     * 正则匹配出现次数
     *
     * @param source 字符
     * @param regex  需要匹配的字符
     * @return 出现次数
     */
    public static Pair<Integer, Integer> getMatchCounts(String source, String regex) {
        Pattern expression = Pattern.compile(regex);
        Matcher matcher = expression.matcher(source);
        int n = 0;
        int end = 0;
        while (matcher.find()) {
            n++;
            end = matcher.end();
        }
        return Pair.create(n, end);
    }

好了以上就是我的解决办法,写完都凌晨了,太困了,代码写的有点乱,大家凑合着看吧!
本人能力有限,如果有不对的地方还是欢迎指正,如果你有好的想法还希望不吝赐教。
写完收工,睡觉去了~~~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值