Java實(shí)現(xiàn)讀取CSV文件并將數(shù)據(jù)放入對(duì)象
CSV(Comma-Separated Values)文件是一種常見的數(shù)據(jù)存儲(chǔ)格式,廣泛應(yīng)用于數(shù)據(jù)交換、日志記錄和表格數(shù)據(jù)處理。在Java開發(fā)中,讀取CSV文件并將數(shù)據(jù)映射到對(duì)象中是常見的需求。本文將詳細(xì)介紹幾種常見方法,包括手動(dòng)解析、使用標(biāo)準(zhǔn)庫(kù)(BufferedReader)、第三方庫(kù)(如OpenCSV),以及通過(guò)反射實(shí)現(xiàn)動(dòng)態(tài)映射,并結(jié)合代碼示例和流程圖說(shuō)明。
一、CSV文件的基本結(jié)構(gòu)
CSV文件由多行文本組成,每行代表一條記錄,字段之間用逗號(hào)(,)分隔。例如:
姓名,年齡,城市
張三,25,北京
李四,30,上海
王五,22,廣州
第一行:表頭(字段名)。
后續(xù)行:數(shù)據(jù)行,字段值與表頭一一對(duì)應(yīng)。
二、手動(dòng)解析CSV文件(使用BufferedReader)
1. 核心思路
通過(guò)BufferedReader逐行讀取文件,使用split()方法分割字段,并手動(dòng)將數(shù)據(jù)映射到對(duì)象中。
2. 代碼示例
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
public class CsvReader {
public static void main(String[] args) {
String csvFile = "data.csv";
String line;
String csvSplitBy = ",";
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
// 讀取表頭
if ((line = br.readLine()) != null) {
String[] headers = line.split(csvSplitBy);
System.out.println("表頭: " + String.join(", ", headers));
}
// 讀取數(shù)據(jù)行
while ((line = br.readLine()) != null) {
String[] data = line.split(csvSplitBy);
Person person = new Person(data[0], Integer.parseInt(data[1]), data[2]);
System.out.println(person);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
class Person {
private String name;
private int age;
private String city;
public Person(String name, int age, String city) {
this.name = name;
this.age = age;
this.city = city;
}
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", city='" + city + "'}";
}
}
3. 流程圖說(shuō)明
[讀取CSV文件] → [逐行讀取] → [分割字段] → [映射到對(duì)象] → [輸出結(jié)果]
4. 優(yōu)點(diǎn)與局限
優(yōu)點(diǎn):代碼簡(jiǎn)單,無(wú)需依賴第三方庫(kù)。
局限:
- 無(wú)法處理字段中的特殊字符(如逗號(hào)、換行符)。
- 需要手動(dòng)處理類型轉(zhuǎn)換(如String轉(zhuǎn)int)。
- 不適合復(fù)雜場(chǎng)景(如嵌套對(duì)象、動(dòng)態(tài)字段)。
三、使用Java標(biāo)準(zhǔn)庫(kù)(Files和Stream)
1. 核心思路
利用Java 8+的Files.lines()和Stream API簡(jiǎn)化讀取過(guò)程,結(jié)合split()方法分割字段。
2. 代碼示例
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;
public class StreamCsvReader {
public static void main(String[] args) {
String csvFile = "data.csv";
String csvSplitBy = ",";
try (Stream<String> stream = Files.lines(Paths.get(csvFile))) {
stream.skip(1) // 跳過(guò)表頭
.forEach(line -> {
String[] data = line.split(csvSplitBy);
Person person = new Person(data[0], Integer.parseInt(data[1]), data[2]);
System.out.println(person);
});
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.流程圖說(shuō)明
[讀取CSV文件] → [跳過(guò)表頭] → [逐行處理] → [映射到對(duì)象] → [輸出結(jié)果]
4. 優(yōu)點(diǎn)與局限
優(yōu)點(diǎn):代碼簡(jiǎn)潔,適合中小型文件。
局限:同樣無(wú)法處理字段中的特殊字符。
四、使用第三方庫(kù)(OpenCSV)
1. 核心思路
OpenCSV是一個(gè)專門處理CSV文件的庫(kù),支持自動(dòng)映射到Java對(duì)象(POJO),并處理復(fù)雜場(chǎng)景(如字段中的逗號(hào)、引號(hào))。
2. 添加依賴
Maven配置:
<dependency>
<groupId>com.opencsv</groupId>
<artifactId>opencsv</artifactId>
<version>5.5.2</version>
</dependency>
3. 代碼示例
(1)定義POJO類
import com.opencsv.bean.CsvBindByName;
public class Person {
@CsvBindByName(column = "姓名")
private String name;
@CsvBindByName(column = "年齡")
private int age;
@CsvBindByName(column = "城市")
private String city;
// Getters and Setters
@Override
public String toString() {
return "Person{name='" + name + "', age=" + age + ", city='" + city + "'}";
}
}
(2)讀取CSV文件
import com.opencsv.bean.CsvToBean;
import com.opencsv.bean.CsvToBeanBuilder;
import java.io.FileReader;
import java.io.IOException;
import java.util.List;
public class OpenCsvReader {
public static void main(String[] args) {
String csvFile = "data.csv";
try (FileReader reader = new FileReader(csvFile)) {
CsvToBean<Person> csvToBean = new CsvToBeanBuilder<Person>(reader)
.withType(Person.class)
.withIgnoreLeadingWhiteSpace(true)
.build();
List<Person> persons = csvToBean.parse();
persons.forEach(System.out::println);
} catch (IOException e) {
e.printStackTrace();
}
}
}
4. 流程圖說(shuō)明
[讀取CSV文件] → [使用OpenCSV解析] → [自動(dòng)映射到對(duì)象] → [輸出結(jié)果]
5. 優(yōu)點(diǎn)與局限
優(yōu)點(diǎn):
- 自動(dòng)處理特殊字符(如逗號(hào)、引號(hào))。
- 支持注解映射,代碼簡(jiǎn)潔。
- 提供類型安全和錯(cuò)誤處理。
局限:需要引入第三方庫(kù)。
五、通過(guò)反射動(dòng)態(tài)映射(高級(jí)方法)
1. 核心思路
利用Java反射機(jī)制動(dòng)態(tài)獲取字段名和值,適用于不確定字段結(jié)構(gòu)的場(chǎng)景(如動(dòng)態(tài)表單數(shù)據(jù))。
2. 代碼示例
import java.io.BufferedReader;
import java.io.FileReader;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
public class ReflectionCsvReader {
public static <T> List<T> readCsv(String csvFile, Class<T> clazz) {
List<T> result = new ArrayList<>();
String line;
String csvSplitBy = ",";
try (BufferedReader br = new BufferedReader(new FileReader(csvFile))) {
// 讀取表頭
if ((line = br.readLine()) != null) {
String[] headers = line.split(csvSplitBy);
// 讀取數(shù)據(jù)行
while ((line = br.readLine()) != null) {
String[] data = line.split(csvSplitBy);
T obj = clazz.getDeclaredConstructor().newInstance();
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
field.setAccessible(true);
field.set(obj, data[i]);
}
result.add(obj);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return result;
}
public static void main(String[] args) {
List<Person> persons = readCsv("data.csv", Person.class);
persons.forEach(System.out::println);
}
}
3. 流程圖說(shuō)明
[讀取CSV文件] → [動(dòng)態(tài)獲取字段] → [反射設(shè)置值] → [輸出對(duì)象]
4. 優(yōu)點(diǎn)與局限
優(yōu)點(diǎn):適用于動(dòng)態(tài)字段場(chǎng)景,無(wú)需硬編碼。
局限:
- 類型安全性差(如字段類型不匹配可能導(dǎo)致運(yùn)行時(shí)錯(cuò)誤)。
- 性能較低(反射操作較慢)。
六、處理特殊字符和編碼問(wèn)題
1. 字段中的特殊字符
如果字段值包含逗號(hào)(如"北京,中國(guó)"),需用雙引號(hào)包裹字段,并手動(dòng)解析:
姓名,年齡,城市
張三,25,"北京,中國(guó)"
2. 編碼問(wèn)題
確保文件編碼與讀取方式一致(如UTF-8):
BufferedReader br = new BufferedReader(
new InputStreamReader(new FileInputStream(csvFile), StandardCharsets.UTF_8)
);
七、最佳實(shí)踐總結(jié)
| 方法 | 適用場(chǎng)景 | 優(yōu)點(diǎn) | 缺點(diǎn) |
|---|---|---|---|
| 手動(dòng)解析 | 簡(jiǎn)單場(chǎng)景 | 無(wú)需依賴庫(kù) | 無(wú)法處理復(fù)雜數(shù)據(jù) |
| BufferedReader | 中小型文件 | 代碼簡(jiǎn)單 | 需手動(dòng)處理類型轉(zhuǎn)換 |
| OpenCSV | 復(fù)雜場(chǎng)景 | 自動(dòng)映射、處理特殊字符 | 需引入第三方庫(kù) |
| 反射動(dòng)態(tài)映射 | 動(dòng)態(tài)字段 | 靈活 | 性能低、類型安全差 |
八、總結(jié)
讀取CSV文件并將數(shù)據(jù)映射到對(duì)象中是Java開發(fā)中的常見需求。根據(jù)項(xiàng)目需求選擇合適的方法:
- 簡(jiǎn)單場(chǎng)景:使用BufferedReader或Stream API。
- 復(fù)雜場(chǎng)景:優(yōu)先使用OpenCSV等第三方庫(kù)。
- 動(dòng)態(tài)字段:結(jié)合反射實(shí)現(xiàn)動(dòng)態(tài)映射。
通過(guò)合理處理特殊字符和編碼問(wèn)題,開發(fā)者可以高效完成CSV數(shù)據(jù)的解析與對(duì)象化,為后續(xù)的數(shù)據(jù)處理和分析提供堅(jiān)實(shí)基礎(chǔ)。
到此這篇關(guān)于Java實(shí)現(xiàn)讀取CSV文件并將數(shù)據(jù)放入對(duì)象的文章就介紹到這了,更多相關(guān)Java讀取CSV內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
如何解決freemarker靜態(tài)化生成html頁(yè)面亂碼的問(wèn)題
這篇文章主要介紹了如何解決freemarker靜態(tài)化生成html頁(yè)面亂碼的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-01-01
JavaIO?BufferedReader和BufferedWriter使用及說(shuō)明
這篇文章主要介紹了JavaIO?BufferedReader和BufferedWriter使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12
springboot全局異常處理方式@ControllerAdvice和@ExceptionHandler
文章總結(jié)了個(gè)人在處理全局異常處理時(shí)的經(jīng)驗(yàn),包括使用`StatusEnum`來(lái)定義狀態(tài)碼,旨在為讀者提供參考,并鼓勵(lì)大家支持腳本之家2024-11-11
SpringBoot使用自動(dòng)配置xxxAutoConfiguration
這篇文章介紹了SpringBoot自動(dòng)配置xxxAutoConfiguration的使用方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-12-12
IntelliJ IDEA配置Maven阿里云鏡像加速源的全流程
國(guó)內(nèi)網(wǎng)絡(luò)訪問(wèn) Maven 中央倉(cāng)庫(kù)經(jīng)常超時(shí)、依賴下載極慢或失敗,配置阿里云等國(guó)內(nèi)鏡像后,Java 項(xiàng)目依賴下載飛快,極大提升開發(fā)效率,是中國(guó)開發(fā)者必做優(yōu)化,本文就給大家介紹了IntelliJ IDEA配置Maven阿里云鏡像加速源的全流程,需要的朋友可以參考下2025-09-09
Java 重寫時(shí)應(yīng)當(dāng)遵守的 11 條規(guī)則
這篇文章主要介紹了Java 重寫時(shí)應(yīng)當(dāng)遵守的 11 條規(guī)則,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-03-03
基于Springboot的高校社團(tuán)管理系統(tǒng)的設(shè)計(jì)與實(shí)現(xiàn)
本文將基于Springboot+Mybatis開發(fā)實(shí)現(xiàn)一個(gè)高校社團(tuán)管理系統(tǒng),系統(tǒng)包含三個(gè)角色:管理員、團(tuán)長(zhǎng)、會(huì)員。文中采用的技術(shù)有Springboot、Mybatis、Jquery、AjAX、JSP等,感興趣的可以了解一下2022-07-07
SpringSecurity?默認(rèn)登錄認(rèn)證的實(shí)現(xiàn)原理解析
這篇文章主要介紹了SpringSecurity?默認(rèn)登錄認(rèn)證的實(shí)現(xiàn)原理解析,本文通過(guò)圖文示例相結(jié)合給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-12-12
關(guān)于兩個(gè)BeanUtils.copyProperties()的用法及區(qū)別
這篇文章主要介紹了關(guān)于兩個(gè)BeanUtils.copyProperties()的用法及區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06

