LineNumberReader.readLine()异常:统计文件<character>行出现次数失败
让我帮你排查下这段代码的问题,顺便给你修正后的版本~
先来说说你这段代码里几个关键的坑:
字符串比较逻辑错误:Java里用
==比较字符串,是判断两个字符串对象的内存引用是否相同,而不是内容是否一致。你要判断行内容是否等于<character>,必须用line.equals("<character>")(区分大小写)或者line.equalsIgnoreCase("<character>")(不区分大小写)。原代码里的line == "<character>"几乎永远不会返回true,除非是极特殊的常量池引用场景。变量声明与初始化不规范:
characterAmount最好显式初始化为0(虽然int默认值是0,但显式写出来更清晰,避免后续维护误解);另外characterAmountReader缺少类型声明,应该写成LineNumberReader characterAmountReader = new LineNumberReader(new FileReader(filename));。不必要的
LineNumberReader:你这里只是统计特定内容的行数,LineNumberReader主要用来获取行号,完全可以用更轻量的BufferedReader替代,当然硬要用LineNumberReader也没问题,但属于功能冗余。资源泄漏与异常缺失:原代码没有处理IO相关异常(比如文件不存在、读取权限不足),也没有关闭文件流,这会导致资源泄漏。推荐用Java 7+的try-with-resources语法,它会自动关闭实现了
AutoCloseable接口的资源,省心又安全。
import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class SpecificLineCounter { public static int countTargetLines(String filename) throws IOException { int characterAmount = 0; // try-with-resources自动关闭流,无需手动调用close() try (BufferedReader reader = new BufferedReader(new FileReader(filename))) { String line; while ((line = reader.readLine()) != null) { // 把常量放前面可以避免line为null时抛出空指针异常 if ("<character>".equals(line)) { characterAmount++; } } } return characterAmount; } public static void main(String[] args) { try { int totalCount = countTargetLines("your-file.txt"); System.out.println("内容为<character>的行数:" + totalCount); } catch (IOException e) { System.err.println("读取文件时出错:" + e.getMessage()); e.printStackTrace(); } } }
- 把常量
<character>放在equals前面("<character>".equals(line))是个实用技巧,这样即使line意外为null(虽然readLine()直到文件结束才会返回null,但能防范其他场景的空指针),也不会抛出异常。 - 如果需要忽略大小写匹配,直接把
equals换成equalsIgnoreCase就行,比如"<character>".equalsIgnoreCase(line)。 - 要是你坚持要用
LineNumberReader,只需要把代码里的BufferedReader替换成LineNumberReader,核心逻辑完全不变,只是它多了getLineNumber()方法,但你这里用不上。
内容的提问来源于stack exchange,提问作者Leres75

