如何在Java中统计目标单词在文本文件中出现的次数

本文

详解如何正确读取文本文件并精确统计用户指定单词在整个文件中的完整匹配次数,修正常见逻辑错误(如仅读首行、误用contains导致子串误判),提供健壮、可运行的java实现方案。

在Java中统计一个单词在文本文件中完整、独立出现的次数(而非作为子字符串被包含),需要同时解决三个关键问题:

  1. 逐行读取整个文件(而非只读第一行);
  2. 按单词边界切分(避免将 "long" 错误匹配到 "longer" 或 "belong" 中);
  3. 区分大小写与标点干扰(如 "Long," 应视为有效匹配)。

原代码中存在两个核心缺陷:

  • szSearch = br.readLine(); 仅读取了文件第一行,后续 while (szSearch.contains(szWord)) 实际是无限循环(因 szSearch 值未更新)或直接跳过;
  • contains() 判断的是子串包含关系,会导致 "long" 匹配 "longer"、"along" 等非目标词,造成统计失真。

✅ 正确做法是:使用 BufferedReader 循环读取每一行,对每行进行空格分割 + 精确单词比对,并推荐使用正则预处理以兼容标点(如英文逗号、句号)。以下是优化后的完整实现:

import java.io.*;
import java.util.Arrays;
import java.util.regex.Pattern;

public class WordCounter {
    public static void main(String[] args) {
        Scanner szKeyboard = new Scanner(System.in);
        BufferedReader br = null;
        try {
            System.out.print("What word are you searching for? ");
            String targetWord = szKeyboard.nextLine().trim();
            if (targetWord.isEmpty()) {
                System.out.println("Error: Search word cannot be empty.");
                return;
            }
            System.out.println("Searching the file...");

            br = new BufferedReader(new FileReader("WORDLIST.txt"));
            String line;
            int count = 0;
            // 使用正则预处理:替换非字母数字字符为空格,确保单词边界清晰
            Pattern nonWord = Pattern.compile("[^a-zA-Z0-9]+");

            while ((line = br.readLine()) != null) {
                // 按空白符分割,并过滤空字符串
                String[] words = nonWord.matcher(line).replaceAll(" ").split("\\s+");
                for (String word : words) {
                    if (!word.isEmpty() && word.equalsIgnoreCase(targetWord)) {
                        count++;
                    }
                }
            }

            System.out.println("The word \"" + targetWord + "\" appears " + count + " times in the file WORDLIST.txt.");

        } catch (FileNotFoundException e) {
            System.out.println("Error - File not found: " + e.getMessage());
        } catch (IOException e) {
            System.out.println("Error - Reading file: " + e.getMessage());
        } finally {
            szKeyboard.close();
            if (br != null) {
                try {
                    br.close();
                } catch (IOException e) {
                    System.out.println("Warning - Failed to close reader: " + e.getMessage());
                }
            }
            System.out.println("\n\n--- File End ---");
        }
    }
}

? 关键改进说明:

  • ✅ 使用 while ((line = br.readLine()) != null) 确保逐行遍历全文
  • ✅ Pattern.compile("[^a-zA-Z0-9]+").matcher(line).replaceAll(" ") 将所有标点、特殊符号统一转为空格,避免 "long," 被当作独立单词遗漏;
  • ✅ split("\\s+") 按任意空白符(空格、制表符、换行等)安全分割;
  • ✅ word.equalsIgnoreCase(targetWord) 支持不区分大小写的精确匹配(如搜索 "Long" 可匹配 "long");
  • ✅ 显式 trim() 和 !word.isEmpty() 过滤空项,防止空字符串干扰计数。

⚠️ 注意事项:

  • 若需严格区分大小写,将 equalsIgnoreCase 替换为 equals;
  • 若文件编码非默认平台编码(如含中文或UTF-8 BOM),建议显式指定:new InputStreamReader(new FileInputStream("WORDLIST.txt"), "UTF-8");
  • 对于超大文件,可考虑使用 Files.lines(Paths.get("WORDLIST.txt")) 配合 Stream API 提升可读性(Java 8+)。

此方案兼顾准确性、鲁棒性与可维护性,可直接集成到实际项目中。