1. 概述
简单来说,CSV(Comma-Separated Values,逗号分隔值)文件是一种以逗号作为分隔符来组织数据的文本格式。
在本篇文章中,我们将介绍几种在 Java 中将 CSV 文件内容读取到数组的不同方法。
2. 示例 CSV 文件
我们使用一个简单的 CSV 文件 book.csv
作为示例:
Mary Kom,Unbreakable
Kapil Isapuari,Farishta
在 Java 程序中,通常我们会定义一个逗号分隔符用于将每一行拆分为独立的值:
public static final String COMMA_DELIMITER = ",";
⚠️ 需要注意的是,并不存在一个通用的分隔符或正则表达式能够处理所有类型的 CSV 值。这不仅适用于包含逗号的字段,也适用于包含其他特殊字符的情况。
如果已有的 CSV 文件中包含分隔符字符(比如逗号)作为值的一部分,而你又无法使用本文提到的方法,那么你需要更换分隔符字符或正则表达式。
在创建新的 CSV 文件时,应选择一个不会出现在任何字段中的字符作为分隔符。
3. 使用 java.io.BufferedReader
最基础的方式是使用 BufferedReader
的 readLine()
方法逐行读取文件,然后根据逗号分隔符将每一行拆分为多个字段:
List<List<String>> records = new ArrayList<>();
try (BufferedReader br = new BufferedReader(new FileReader("book.csv"))) {
String line;
while ((line = br.readLine()) != null) {
String[] values = line.split(COMMA_DELIMITER);
records.add(Arrays.asList(values));
}
}
✅ 简单粗暴,适合处理结构简单的 CSV 文件。
4. 使用 java.util.Scanner
另一种方式是使用 Scanner
类按行读取文件内容:
List<List<String>> records = new ArrayList<>();
try (Scanner scanner = new Scanner(new File("book.csv"))) {
while (scanner.hasNextLine()) {
records.add(getRecordFromLine(scanner.nextLine()));
}
}
接着,我们将每一行解析为一个字符串列表:
private List<String> getRecordFromLine(String line) {
List<String> values = new ArrayList<String>();
try (Scanner rowScanner = new Scanner(line)) {
rowScanner.useDelimiter(COMMA_DELIMITER);
while (rowScanner.hasNext()) {
values.add(rowScanner.next());
}
}
return values;
}
这种方式逻辑清晰,适合喜欢封装逻辑的开发者。
5. 使用 Files
工具类
Java 7 引入了 java.nio.file.Files
工具类,提供了多种静态方法来处理文件。下面介绍几种基于 Files
的读取方式。
5.1. 使用 Files#lines
Java 8 中新增的 lines()
方法可以将文件内容作为 Stream 来处理,适合进行函数式编程风格的处理:
try (Stream<String> lines = Files.lines(Paths.get(CSV_FILE))) {
List<List<String>> records = lines.map(line -> Arrays.asList(line.split(COMMA_DELIMITER)))
.collect(Collectors.toList());
}
其中,Paths.get(CSV_FILE)
返回一个 Path
实例,代表文件路径。我们使用 map()
将每一行转换为字符串列表。
✅ 适合处理中等大小的文件,结合 Stream API 可读性更强。
5.2. 使用 Files#readAllLines
readAllLines()
方法会一次性将整个文件加载到内存中,返回每行内容组成的列表:
List<List<String>> records = Files.readAllLines(Paths.get(CSV_FILE))
.stream()
.map(line -> Arrays.asList(line.split(COMMA_DELIMITER)))
.collect(Collectors.toList());
⚠️ 注意:该方法会将整个文件读入内存,不适合处理大文件。
5.3. 使用 Files#newBufferedReader
该方法返回一个 BufferedReader
实例,适合处理大文件:
try (BufferedReader reader = Files.newBufferedReader(Paths.get(CSV_FILE))) {
List<List<String>> records = reader.lines()
.map(line -> Arrays.asList(line.split(COMMA_DELIMITER)))
.collect(Collectors.toList());
}
✅ 推荐在处理大文件时使用此方式,效率更高。
6. 处理字段中包含逗号的情况
当 CSV 文件中的字段本身包含逗号时,使用简单的逗号分隔符会导致字段被错误拆分。例如:
"Kom, Mary",Unbreakable
"Isapuari, Kapil",Farishta
此时,直接使用 split(",")
会导致 "Kom, Mary"
被错误地拆分为 "Kom
和 Mary"
。
6.1. 使用自定义 CSV 解析器
我们可以实现一个简单的解析器,使用 StringBuilder
和引号标记来处理带逗号的字段:
List<List<String>> records = new ArrayList<List<String>>();
try (BufferedReader br = new BufferedReader(new FileReader(CSV_FILE))) {
String line = "";
while ((line = br.readLine()) != null) {
records.add(parseLine(line));
}
}
解析方法如下:
private static List<String> parseLine(String line) {
List values = new ArrayList<>();
boolean inQuotes = false;
StringBuilder currentValue = new StringBuilder();
for (char c : line.toCharArray()) {
if (c == '"') {
inQuotes = !inQuotes;
} else if (c == ',' && !inQuotes) {
values.add(currentValue.toString());
currentValue = new StringBuilder();
} else {
currentValue.append(c);
}
}
values.add(currentValue.toString());
return values;
}
✅ 适合需要处理复杂字段的场景,无需引入第三方库。
6.2. 使用其他分隔符
我们可以使用其他符号(如 |
, /
, ;
)作为分隔符。例如:
"Kom, Mary"|Unbreakable
"Isapuari, Kapil"|Farishta
此时,我们只需要将分隔符改为:
public static final String COMMA_DELIMITER = "\\|";
⚠️ 注意在正则表达式中需要对特殊字符进行转义。
7. 使用 OpenCSV
OpenCSV 是一个强大的第三方库,专门用于处理 CSV 文件。它默认支持字段中包含逗号的情况:
List<List<String>> records = new ArrayList<List<String>>();
try (CSVReader csvReader = new CSVReader(new FileReader("book.csv"));) {
String[] values = null;
while ((values = csvReader.readNext()) != null) {
records.add(Arrays.asList(values));
}
}
✅ 对于复杂 CSV 文件,OpenCSV 是首选方案。支持字段引号、换行、转义等特性。
"Kom, Mary",Unbreakable
"Isapuari, Kapil",Farishta
更多关于 OpenCSV 的使用,请参考官方文档或我们的 OpenCSV 教程。
8. 总结
本文介绍了多种将 CSV 文件读入 Java 数组的方式:
- 基础方式:
BufferedReader
,Scanner
- Java 7+ 工具类:
Files.lines
,Files.readAllLines
,Files.newBufferedReader
- 高级方式:自定义解析器、更换分隔符
- 第三方库:OpenCSV
对于包含特殊字符的字段,建议使用 OpenCSV 或自定义解析器,以避免数据错误。
✅ 小结:
- 简单场景 →
BufferedReader + split
- 复杂场景 → OpenCSV 或自定义解析器
- 大文件 →
Files.newBufferedReader
+ Stream API