
在Java应用程序中,对文本文件进行内容分析是常见的需求,例如统计文件的总行数、查找特定内容出现的行数等。为了封装这些功能,我们可以设计一个名为FileStats的类。
FileStats类的核心职责是:
其基本结构定义如下:
getNumLines() 方法的目标是读取文件并计算其包含的行数。实现此功能,我们需要使用java.io.File来表示文件,以及java.util.Scanner来逐行读取文件内容。为了确保资源(文件句柄)的正确关闭,即使发生异常,也应采用Java 7及以上版本引入的try-with-resources语句。
立即学习“Java免费学习笔记(深入)”;
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileStats {
private String filename;
public FileStats(String f) {
this.filename = f;
}
/**
* 计算文件的总行数。
*
* @return 文件的总行数。
* @throws FileNotFoundException 如果指定的文件不存在。
*/
public int getNumLines() throws FileNotFoundException {
File fileObj = new File(filename);
int numLines = 0;
// 使用 try-with-resources 确保 Scanner 资源被自动关闭
try (Scanner inputFile = new Scanner(fileObj)) {
while (inputFile.hasNextLine()) {
inputFile.nextLine(); // 读取一行但不需要其内容
numLines++;
}
} // Scanner 会在这里自动关闭
return numLines;
}
// 其他方法将在此处添加
}代码解析:
getNumLinesThatContain() 方法旨在查找文件中包含特定key文本的行数,且查找过程不区分大小写。此方法与getNumLines()类似,都需要读取文件,但在此基础上增加了内容匹配的逻辑。
常见陷阱分析:new Scanner(filename) 的误用
在实现此方法时,一个常见的错误是尝试使用new Scanner(filename)来初始化Scanner。例如:
// 错误示例:试图从字符串字面量 "filename" 中读取,而非文件内容 // inputFile = new Scanner(filename);
当您将一个String类型的变量直接传递给Scanner的构造函数时,Scanner会将其视为要扫描的“文本字符串”本身,而不是一个文件路径。这意味着Scanner将尝试从字符串"your_file_name.txt"中读取内容,而不是打开并读取your_file_name.txt这个文件的实际内容。这会导致Scanner很快就没有更多内容可读(因为它只读取了作为其输入参数的那个字符串),从而返回不正确的结果(通常是0或1)。
正确初始化 Scanner
正确的做法是始终将File对象传递给Scanner构造函数,以便Scanner能够正确地打开并读取文件内容。
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileStats {
private String filename;
public FileStats(String f) {
this.filename = f;
}
// ... getNumLines() 方法 ...
/**
* 计算文件中包含指定文本的行数(不区分大小写)。
* 一行中无论包含多少次关键词,只计数一次。
*
* @param key 要搜索的文本。
* @return 包含指定文本的行数。
* @throws FileNotFoundException 如果指定的文件不存在。
*/
public int getNumLinesThatContain(String key) throws FileNotFoundException {
File fileObj = new File(filename);
int numLines = 0;
try (Scanner inputFile = new Scanner(fileObj)) { // 修正:从 File 对象读取
while (inputFile.hasNextLine()) {
String line = inputFile.nextLine();
// 将行内容和搜索关键词都转换为大写,然后进行包含性检查
if (line.toUpperCase().contains(key.toUpperCase())) {
numLines++;
}
}
}
return numLines;
}
}代码解析:
结合上述两个方法,一个完整的FileStats类实现如下:
import java.io.File;
import java.io.FileNotFoundException;
import java.util.Scanner;
public class FileStats {
private String filename;
/**
* 构造函数,初始化 FileStats 对象。
*
* @param f 要分析的文件路径。
*/
public FileStats(String f) {
this.filename = f;
}
/**
* 计算文件的总行数。
*
* @return 文件的总行数。
* @throws FileNotFoundException 如果指定的文件不存在。
*/
public int getNumLines() throws FileNotFoundException {
File fileObj = new File(filename);
int numLines = 0;
try (Scanner inputFile = new Scanner(fileObj)) {
while (inputFile.hasNextLine()) {
inputFile.nextLine();
numLines++;
}
}
return numLines;
}
/**
* 计算文件中包含指定文本的行数(不区分大小写)。
* 一行中无论包含多少次关键词,只计数一次。
*
* @param key 要搜索的文本。
* @return 包含指定文本的行数。
* @throws FileNotFoundException 如果指定的文件不存在。
*/
public int getNumLinesThatContain(String key) throws FileNotFoundException {
File fileObj = new File(filename);
int numLines = 0;
try (Scanner inputFile = new Scanner(fileObj)) {
while (inputFile.hasNextLine()) {
String line = inputFile.nextLine();
if (line.toUpperCase().contains(key.toUpperCase())) {
numLines++;
}
}
}
return numLines;
}
// 示例主方法,用于测试
public static void main(String[] args) {
// 创建一个用于测试的文件
// 假设当前目录下有一个名为 "test.txt" 的文件,内容如下:
// Hello World
// hello java
// Java Programming
// This is a test line.
// Hello again.
String testFileName = "test.txt"; // 请确保此文件存在于运行目录下或提供完整路径
// 简单的文件创建辅助函数 (实际应用中文件应已存在)
try {
java.io.FileWriter writer = new java.io.FileWriter(testFileName);
writer.write("Hello World\n");
writer.write("hello java\n");
writer.write("Java Programming\n");
writer.write("This is a test line.\n");
writer.write("Hello again.\n");
writer.close();
} catch (java.io.IOException e) {
System.err.println("创建测试文件失败: " + e.getMessage());
return;
}
try {
FileStats stats = new FileStats(testFileName);
// 测试 getNumLines()
int totalLines = stats.getNumLines();
System.out.println("文件总行数: " + totalLines); // 预期输出: 5
// 测试 getNumLinesThatContain()
String searchKey1 = "hello";
int linesWithHello = stats.getNumLinesThatContain(searchKey1);
System.out.println("包含 '" + searchKey1 + "' 的行数: " + linesWithHello); // 预期输出: 3 (Hello World, hello java, Hello again.)
String searchKey2 = "java";
int linesWithJava = stats.getNumLinesThatContain(searchKey2);
System.out.println("包含 '" + searchKey2 + "' 的行数: " + linesWithJava); // 预期输出: 2 (hello java, Java Programming)
String searchKey3 = "nonexistent";
int linesWithNonexistent = stats.getNumLinesThatContain(searchKey3);
System.out.println("包含 '" + searchKey3 + "' 的行数: " + linesWithNonexistent); // 预期输出: 0
} catch (FileNotFoundException e) {
System.err.println("错误:文件未找到 - " + e.getMessage());
}
}
}通过本文,我们学习了如何构建一个FileStats类来执行基本的文件内容统计任务。关键点在于:
掌握这些基本的文件I/O操作和错误处理技巧,是进行更复杂Java文件处理任务的基础。
以上就是Java文件内容统计:实现行数与关键词查找功能及常见陷阱的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号