Java中csv文件讀寫超詳細(xì)分析
一、txt、csv、tsv文件
txt、csv、tsv都屬于文本文件
文件類型 | 英文全稱 | 名稱 | 分隔符 | 描述 |
---|---|---|---|---|
txt | text | 文本類型 | 沒(méi)有明確要求 | 可以有分隔符,也可以沒(méi)有 |
csv | Comma-separated values | 逗號(hào)分隔值類型 | 半角逗號(hào):',' | csv是txt的特殊類型 |
tsv | Tab-separated values | 制表符分隔值 | 制表符:'\t' | tsv是txt的特殊類型 |
csv又有叫做Char-separated values(字符分隔值類型),通過(guò)字符值進(jìn)行分隔。
但因?yàn)榘虢嵌禾?hào)在數(shù)據(jù)中出現(xiàn)的的可能性比較大,所以經(jīng)常會(huì)使用文本包裝符來(lái)標(biāo)識(shí)逗號(hào)為數(shù)據(jù)中的一部分,或者直接使用其它特殊符號(hào)作為分隔符。
二、csv文件規(guī)范
- 每一行記錄位于一個(gè)單獨(dú)的行上,用回車換行符CRLF(\r\n)分割。
- 文件中的最后一行記錄可以有結(jié)尾回車換行符,也可以沒(méi)有。
- 第一行可以存在一個(gè)可選的標(biāo)題頭,格式和普通記錄行的格式一樣。標(biāo)題頭要包含文件記錄字段對(duì)應(yīng)的名稱,應(yīng)該有和記錄字段一樣的數(shù)量。
- 在標(biāo)題頭行和普通行每行記錄中,會(huì)存在一個(gè)或多個(gè)由半角逗號(hào)(,)分隔的字段。整個(gè)文件中每行應(yīng)包含相同數(shù)量的字段,空格也是字段的一部分,不應(yīng)被忽略。每一行記錄最后一個(gè)字段后不能跟逗號(hào)。(通常用逗號(hào)分隔,也有其他字符分隔的CSV,需事先約定)
- 每個(gè)字段可用也可不用半角雙引號(hào)(")(文本包裝符)括起來(lái)(如Microsoft的Excel就根本不用雙引號(hào))。如果字段沒(méi)有用引號(hào)括起來(lái),那么該字段內(nèi)部不能出現(xiàn)雙引號(hào)字符。
- 字段中若包含回車換行符、雙引號(hào)或者逗號(hào),該字段需要用雙引號(hào)括起來(lái)。
- 如果用雙引號(hào)括字段,那么出現(xiàn)在字段內(nèi)的雙引號(hào)前必須再加一個(gè)雙引號(hào)進(jìn)行轉(zhuǎn)義。
三、csv使用場(chǎng)景
csv文件經(jīng)常用于導(dǎo)出大批量數(shù)據(jù)(csv比excel更輕量級(jí),更適合大批量數(shù)據(jù))。
csv與excel對(duì)比:
- csv只能用于存儲(chǔ)純文本內(nèi)容,excel不僅支持純文本內(nèi)容還支持二進(jìn)制數(shù)據(jù)
- csv可以看做是excel的輕量級(jí)簡(jiǎn)單版實(shí)現(xiàn),excel比csv更加強(qiáng)大
- csv文件可以被excel軟件直接打開(kāi),csv文件一般用于表格數(shù)據(jù)的傳輸
四、Java中的csv類庫(kù)
java中的csv的類庫(kù)主要有以下幾類:
- javacsv:javacsv在2014-12-10就不維護(hù)了
- opencsv:opencsv是apache的項(xiàng)目,至今仍在維護(hù)
1. javacsv
2. opencsv
opencsv是一個(gè)用Java來(lái)分析和生成csv文件的框架。通常用來(lái)bean的寫入csv文件和從csv文件讀出bean,并支持注解的方式。
maven依賴:
<dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>5.6</version> </dependency>
寫入器
名稱 | 描述 |
---|---|
CSVWriter | 簡(jiǎn)單的CSV寫入器 |
CSVParserWriter | 通過(guò)CSVParser解析數(shù)據(jù)的寫入器 |
StatefulBeanToCsv | 直接將bean寫入CSV的寫入器 |
讀取器
名稱 | 描述 |
---|---|
CSVReader | 簡(jiǎn)單的CSV讀取器 |
CsvToBean | CSV讀取為bean的讀取器 |
CSVReaderHeaderAware |
解析器
名稱 | 描述 |
---|---|
CSVParser | 簡(jiǎn)單的CSV解析器 |
RFC4180Parser | 基于RFC4180規(guī)范的解析器 |
注解
注解 | 描述 | 主要屬性 |
---|---|---|
@CsvBindByName | 按表頭名稱綁定 | required:必須字段,默認(rèn)為false.該字段為空拋異常 column:對(duì)象列標(biāo)題名稱 |
@CsvBindByPosition | 按位置綁定 | required:必須字段,默認(rèn)為false.該字段為空拋異常 position:位置索引 |
@CsvCustomBindByName | 與CsvBindByName相同,但必須提供自己的數(shù)據(jù)轉(zhuǎn)換類 | required:必須字段,默認(rèn)為false.該字段為空拋異常 column:對(duì)象列標(biāo)題名稱 converter:轉(zhuǎn)換器 |
@CsvCustomBindByPosition | 與CsvBindByPosition相同,但必須提供自己的數(shù)據(jù)轉(zhuǎn)換類 | required:必須字段,默認(rèn)為false.該字段為空拋異常 column:對(duì)象列標(biāo)題名稱 converter:轉(zhuǎn)換器 |
@CsvBindAndJoinByName | 應(yīng)用于MultiValuedMap集合類型的bean字段,通過(guò)標(biāo)題名稱綁定 | required:必須字段,默認(rèn)為false.該字段為空拋異常 column:對(duì)象列標(biāo)題名稱 converter:轉(zhuǎn)換器 mapType:集合類型 elementTyp:元素類型 |
@CsvBindAndJoinByPosition | 應(yīng)用于MultiValuedMap集合類型的bean字段,通過(guò)位置索引綁定 | required:必須字段,默認(rèn)為false.該字段為空拋異常 position:位置索引 converter:轉(zhuǎn)換器 mapType:集合類型 elementTyp:元素類型 |
@CsvBindAndSplitByName | 應(yīng)用于Collection集合類型的bean字段,通過(guò)標(biāo)題名稱綁定 | required:必須字段,默認(rèn)為false.該字段為空拋異常 column:對(duì)象列標(biāo)題名稱 converter:轉(zhuǎn)換器 mapType:集合類型 elementTyp:元素類型 splitOn: |
@CsvBindAndSplitByPosition | 應(yīng)用于Collection集合類型的bean字段,通過(guò)位置索引綁定 | required:必須字段,默認(rèn)為false.該字段為空拋異常 position:位置索引 converter:轉(zhuǎn)換器 mapType:集合類型 elementTyp:元素類型 splitOn: |
@CsvDate | 應(yīng)用于日期/時(shí)間類型的bean字段,與上面相關(guān)的綁定注解結(jié)合使用 | value:日期格式,例如:yyyy-MM-dd |
@CsvNumber | 應(yīng)用于數(shù)字類型的bean字段,與上面相關(guān)的綁定注解結(jié)合使用 | value:數(shù)字格式,例如:000.### |
映射策略
名稱 | 描述 | 重要方法 | 方法描述 |
---|---|---|---|
ColumnPositionMappingStrategy | 列位置映射策略,用于沒(méi)有頭文件(標(biāo)題行)的文件 | setColumnMapping(String… columnMapping | 設(shè)置要映射的列名集合,集合下標(biāo)即為列寫入順序 |
HeaderColumnNameMappingStrategy | 標(biāo)題列名稱映射策略, | setColumnOrderOnWrite(Comparator writeOrder) | 通過(guò)比較器,設(shè)置列寫入順序 |
HeaderColumnNameTranslateMappingStrategy | 標(biāo)題列名稱翻譯映射策略 bean的屬性名可以與csv列頭不一樣,通過(guò)指定map來(lái)映射。 | setColumnMapping(Map<String, String> columnMapping) | 設(shè)置標(biāo)題名與列名的映射 |
FuzzyMappingStrategy |
① ColumnPositionMappingStrategy
使用該映射策略需要csv文件沒(méi)有標(biāo)題行。該策略通過(guò)設(shè)置列的下標(biāo)位置來(lái)指定列的順序,有兩種方式來(lái)設(shè)置列的下標(biāo):
- 通過(guò)CsvBindByPosition、CsvCustomBindByPosition、CsvBindAndJoinByPosition、CsvBindAndSplitByPosition注解來(lái)設(shè)置列的下標(biāo)
- 通過(guò)setColumnMapping(String… columnMapping)方法來(lái)設(shè)置列的下標(biāo)
② HeaderColumnNameMappingStrategy
該映射策略用于有標(biāo)題行的csv文件。該策略通過(guò)指定比較器來(lái)指定列的順序:
- 通過(guò)setColumnOrderOnWrite(Comparator writeOrder)指定比較器
關(guān)于標(biāo)題列的名稱:
- 默認(rèn)使用bean的字段名稱大寫作為標(biāo)題列的名稱
- 如果使用CsvBindByName、CsvCustomBindByName、CsvBindAndJoinByName、CsvBindAndSplitByName注解的column屬性指定列名稱,則使用該值,否則使用bean的字段名稱大寫作為標(biāo)題列的名稱
③ HeaderColumnNameTranslateMappingStrategy
該映射策略用于有標(biāo)題行的csv文件。該策略通過(guò)映射Map來(lái)指定標(biāo)題列名與bean的屬性名映射關(guān)系。
映射Map的key=標(biāo)題列名,value=bean的屬性名。
需要注意:
- 該映射策略只適用于讀取csv文件時(shí),指定標(biāo)題列名與bean的屬性名的映射關(guān)系
- 該映射策略不適用于寫入csv文件時(shí),指定bean的屬性名與標(biāo)題列名的映射關(guān)系(不要誤解)
過(guò)濾器
名稱 | 描述 |
---|---|
CsvToBeanFilter | 讀取時(shí)根據(jù)過(guò)濾規(guī)則過(guò)濾掉一些行 |
主要方法:boolean allowLine(String[] line)
- 入?yún)⒅械膌ine表示一行數(shù)據(jù)的集合
- 返回值為false的這行數(shù)據(jù)被將被過(guò)濾掉
構(gòu)建器
名稱 | 描述 |
---|---|
CSVWriterBuilder | CSV寫入構(gòu)建器,構(gòu)建CSVWriter或CSVParserWriter |
StatefulBeanToCsvBuilder | 對(duì)象寫入CSV構(gòu)建器,構(gòu)建StatefulBeanToCsv |
CSVReaderBuilder | CSV讀取構(gòu)建器,構(gòu)建CSVReader |
CsvToBeanBuilder | CSV讀取對(duì)象構(gòu)建器,構(gòu)建CsvToBean |
CSVReaderHeaderAwareBuilder | 構(gòu)建CSVReaderHeaderAware |
CSVParserBuilder | CSV解析器構(gòu)造器,構(gòu)建CSVParser |
RFC4180ParserBuilder | RFC4180解析器構(gòu)造器,構(gòu)建RFC4180Parser |
寫入方式
User類:
@Data @NoArgsConstructor @AllArgsConstructor public class User { public String userId; public String userName; public String sex; }
User1類:
@Data @NoArgsConstructor @AllArgsConstructor public class User1 { @CsvBindByPosition(position = 0) public String userId; @CsvBindByPosition(position = 1) public String userName; @CsvBindByPosition(position = 2) public String sex; }
User2類:
@Data @NoArgsConstructor @AllArgsConstructor public class User2 { @CsvBindByName(column = "用戶ID") public String userId; @CsvBindByName(column = "用戶名") public String userName; @CsvBindByName(column = "性別") public String sex; }
① 簡(jiǎn)單的寫入
CSVWriter的主要參數(shù):
- Writer writer:指定需要寫入的源文件
- char separator:分隔符(默認(rèn)逗號(hào))
- char quotechar:文本邊界符(默認(rèn)雙引號(hào))
- 如果數(shù)據(jù)中包含分隔符,需要使用文本邊界符包裹數(shù)據(jù)。通常用雙引號(hào)、單引號(hào)或斜杠作為文本邊界符
- char escapechar:轉(zhuǎn)義字符(默認(rèn)雙引號(hào))
- String lineend:行分隔符(默認(rèn)為\n)
使用方法:
/** * 簡(jiǎn)單的寫入 * @throws Exception */ private static void csvWriter() throws Exception { // 寫入位置 String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; // 標(biāo)題行 String[] titleRow = {"用戶ID", "用戶名", "性別"}; // 數(shù)據(jù)行 ArrayList<String[]> dataRows = new ArrayList<>(); String[] dataRow1 = {"1", "張三", "男"}; String[] dataRow2 = {"2", "李四", "男"}; String[] dataRow3 = {"3", "翠花", "女"}; dataRows.add(dataRow1); dataRows.add(dataRow2); dataRows.add(dataRow3); OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileName), Charset.forName("UTF-8")); // 1. 通過(guò)new CSVWriter對(duì)象的方式直接創(chuàng)建CSVWriter對(duì)象 // CSVWriter csvWriter = new CSVWriter(writer); // 2. 通過(guò)CSVWriterBuilder構(gòu)造器構(gòu)建CSVWriter對(duì)象 CSVWriter csvWriter = (CSVWriter) new CSVWriterBuilder(writer) .build(); // 寫入標(biāo)題行 csvWriter.writeNext(titleRow, false); // 寫入數(shù)據(jù)行 csvWriter.writeAll(dataRows, false); csvWriter.close(); }
demo.csv內(nèi)容:
用戶ID,用戶名,性別
1,張三,男
2,李四,男
3,翠花,女
② 基于位置映射的寫入
使用方法:
/** * 基于位置映射的寫入 * @throws Exception */ private static void beanToCsvByPosition() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; List<User> list = new ArrayList<>(); list.add(new User("1", "張三", "男")); list.add(new User("2", "李四", "男")); list.add(new User("3", "翠花", "女")); OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileName), Charset.forName("UTF-8")); ColumnPositionMappingStrategy<User> strategy = new ColumnPositionMappingStrategy(); // 未指定的列不寫入 String[] columns = new String[] { "userId", "userName", "sex"}; strategy.setColumnMapping(columns); strategy.setType(User.class); // 如果需要標(biāo)題行,可這樣寫入 // CSVWriter csvWriter = (CSVWriter) new CSVWriterBuilder(writer) // .build(); // String[] titleRow = {"用戶ID", "用戶名", "性別"}; // csvWriter.writeNext(titleRow, false); StatefulBeanToCsv<User> statefulBeanToCsv = new StatefulBeanToCsvBuilder<User>(writer) .withMappingStrategy(strategy) .withApplyQuotesToAll(false) .build(); statefulBeanToCsv.write(list); writer.close(); }
demo.csv內(nèi)容:
1,張三,男
2,李四,男
3,翠花,女
③ 基于CsvBindByPosition注解映射的寫入
使用方法:
/** * 基于CsvBindByPosition注解映射的寫入 * @throws Exception */ private static void beanToCsvByPositionAnnotation() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; List<User1> list = new ArrayList<>(); list.add(new User1("1", "張三", "男")); list.add(new User1("2", "李四", "男")); list.add(new User1("3", "翠花", "女")); // 未使用@CsvBindByPosition注解的列不寫入 OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileName), Charset.forName("UTF-8")); // 如果需要標(biāo)題行,可這樣寫入 // CSVWriter csvWriter = (CSVWriter) new CSVWriterBuilder(writer) // .build(); // String[] titleRow = {"用戶ID", "用戶名", "性別"}; // csvWriter.writeNext(titleRow, false); StatefulBeanToCsv<User1> statefulBeanToCsv = new StatefulBeanToCsvBuilder<User1>(writer) .withApplyQuotesToAll(false) .build(); statefulBeanToCsv.write(list); writer.close(); }
demo.csv內(nèi)容:
1,張三,男
2,李四,男
3,翠花,女
④ 基于列名映射的寫入
使用方法:
/** * 基于列名映射的寫入 * @throws Exception */ private static void beanToCsvByName() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; List<User> list = new ArrayList<>(); list.add(new User("1", "張三", "男")); list.add(new User("2", "李四", "男")); list.add(new User("3", "翠花", "女")); OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileName), Charset.forName("UTF-8")); // 可通過(guò)比較器指定列的順序 // 標(biāo)題行的列名默認(rèn)為bean的字段名大寫 HeaderColumnNameMappingStrategy<User> strategy = new HeaderColumnNameMappingStrategy<>(); HashMap<String, Integer> columnOrderMap = new HashMap<>(); columnOrderMap.put("USERID", 1); columnOrderMap.put("SEX", 10); columnOrderMap.put("USERNAME", 100); strategy.setColumnOrderOnWrite(Comparator.comparingInt(column -> (columnOrderMap.getOrDefault(column, 0)))); strategy.setType(User.class); StatefulBeanToCsv<User> statefulBeanToCsv = new StatefulBeanToCsvBuilder<User>(writer) .withMappingStrategy(strategy) .withApplyQuotesToAll(false) .build(); statefulBeanToCsv.write(list); writer.close(); }
demo.csv內(nèi)容:
用戶ID,用戶名,性別
1,張三,男
2,李四,男
3,翠花,女
⑤ 基于CsvBindByName注解映射的寫入
使用方法:
/** * 基于CsvBindByName注解映射的寫入 * @throws Exception */ private static void beanToCsvByNameAnnotation() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; List<User2> list = new ArrayList<>(); list.add(new User2("1", "張三", "男")); list.add(new User2("2", "李四", "男")); list.add(new User2("3", "翠花", "女")); OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(fileName), Charset.forName("UTF-8")); // 可通過(guò)比較器指定列的順序 // 通過(guò)CsvBindByName注解的column屬性,指定標(biāo)題行的列名 HeaderColumnNameMappingStrategy<User2> strategy = new HeaderColumnNameMappingStrategy<>(); // 注意這里的key是指的標(biāo)題行的列名 HashMap<String, Integer> columnOrderMap = new HashMap<>(); columnOrderMap.put("用戶ID", 1); columnOrderMap.put("用戶名", 10); columnOrderMap.put("性別", 100); strategy.setColumnOrderOnWrite(Comparator.comparingInt(column -> (columnOrderMap.getOrDefault(column, 0)))); strategy.setType(User2.class); StatefulBeanToCsv<User2> statefulBeanToCsv = new StatefulBeanToCsvBuilder<User2>(writer) .withMappingStrategy(strategy) .withApplyQuotesToAll(false) .build(); statefulBeanToCsv.write(list); writer.close(); }
demo.csv內(nèi)容:
用戶ID,用戶名,性別
1,張三,男
2,李四,男
3,翠花,女
讀取方式
通過(guò)簡(jiǎn)單的寫入寫入的數(shù)據(jù)
① 簡(jiǎn)單的讀取
使用方法:
/** * 簡(jiǎn)單的讀取 * @throws Exception */ private static void csvReader() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName), Charset.forName("UTF-8")); CSVReader csvReader = new CSVReaderBuilder(reader).build(); List<String[]> list = csvReader.readAll(); for (String[] strings : list) { System.out.println(JSON.toJSONString(strings)); } csvReader.close(); }
控制臺(tái)日志:
["用戶ID","用戶名","性別"]
["1","張三","男"]
["2","李四","男"]
["3","翠花","女"]
② 基于位置映射的讀取
通過(guò)基于位置映射的寫入寫入的數(shù)據(jù)
使用方法:
/** * 基于位置映射的讀取 * @throws Exception */ private static void csvToBeanByPosition() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName), Charset.forName("UTF-8")); // 不需要標(biāo)題行,列的順序通過(guò)列位置映射指定 ColumnPositionMappingStrategy<User> strategy = new ColumnPositionMappingStrategy(); String[] columns = new String[] { "userId", "userName", "sex"}; strategy.setColumnMapping(columns); strategy.setType(User.class); CsvToBean<User> csvToBean = new CsvToBeanBuilder<User>(reader) .withMappingStrategy(strategy) .build(); List<User> list = csvToBean.parse(); for (User user : list) { System.out.println(JSON.toJSONString(user)); } reader.close(); }
控制臺(tái)日志:
{"sex":"男","userId":"1","userName":"張三"}
{"sex":"男","userId":"2","userName":"李四"}
{"sex":"女","userId":"3","userName":"翠花"}
③ 基于CsvBindByPosition注解映射的讀取
通過(guò)基于CsvBindByPosition注解映射的寫入寫入的數(shù)據(jù)
使用方法:
/** * 基于CsvBindByPosition注解映射的讀取 * @throws Exception */ private static void csvToBeanByPositionAnnotation() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName), Charset.forName("UTF-8")); // 不需要標(biāo)題行,列的順序通過(guò)CsvBindByPosition注解的position屬性指定 CsvToBean<User1> csvToBean = new CsvToBeanBuilder<User1>(reader) .withType(User1.class) .build(); List<User1> list = csvToBean.parse(); for (User1 user : list) { System.out.println(JSON.toJSONString(user)); } reader.close(); }
控制臺(tái)日志:
{"sex":"男","userId":"1","userName":"張三"}
{"sex":"男","userId":"2","userName":"李四"}
{"sex":"女","userId":"3","userName":"翠花"}
④ 基于列名映射的讀取
通過(guò)基于列名映射的寫入寫入的數(shù)據(jù)
使用方法:
/** * 基于列名映射的讀取 * @throws Exception */ private static void csvToBeanByName() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName), Charset.forName("UTF-8")); // bean的字段名稱大寫為標(biāo)題列名 CsvToBean<User> csvToBean = new CsvToBeanBuilder<User>(reader) .withType(User.class) .build(); List<User> list = csvToBean.parse(); for (User user : list) { System.out.println(JSON.toJSONString(user)); } reader.close(); }
控制臺(tái)日志:
{"sex":"男","userId":"1","userName":"張三"}
{"sex":"男","userId":"2","userName":"李四"}
{"sex":"女","userId":"3","userName":"翠花"}
⑤ 基于CsvBindByName注解映射的讀取
通過(guò)基于CsvBindByName注解映射的寫入寫入的數(shù)據(jù)
使用方法:
private static void csvToBeanByNameAnnotation() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName), Charset.forName("UTF-8")); // CsvBindByName注解的column屬性為標(biāo)題列名 CsvToBean<User2> csvToBean = new CsvToBeanBuilder<User2>(reader) .withType(User2.class) .build(); List<User2> list = csvToBean.parse(); for (User2 user : list) { System.out.println(JSON.toJSONString(user)); } reader.close(); }
控制臺(tái)日志:
{"sex":"男","userId":"1","userName":"張三"}
{"sex":"男","userId":"2","userName":"李四"}
{"sex":"女","userId":"3","userName":"翠花"}
⑥ 基于列名轉(zhuǎn)換映射的讀取
通過(guò)基于CsvBindByName注解映射的讀取寫入的數(shù)據(jù)
使用方法:
public class MyCsvToBeanFilter implements CsvToBeanFilter { @Override public boolean allowLine(String[] line) { // 過(guò)濾掉用戶名為李四的行 if("李四".equals(line[1])){ return false; } return true; } }
/** * 基于列名轉(zhuǎn)換映射的讀取 * @throws Exception */ private static void csvToBeanByColumnNameTranslateMapping() throws Exception { String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath(); String fileName = classpath+"test/demo.csv"; InputStreamReader reader = new InputStreamReader(new FileInputStream(fileName), Charset.forName("UTF-8")); // 指定標(biāo)題列名和bean列名映射關(guān)系 HeaderColumnNameTranslateMappingStrategy<User> strategy = new HeaderColumnNameTranslateMappingStrategy<>(); // key:標(biāo)題列名,value:bean的屬性名 HashMap<String, String> columnMappingMap = new HashMap<>(); columnMappingMap.put("用戶ID", "userId"); columnMappingMap.put("性別", "sex"); columnMappingMap.put("用戶名", "userName"); strategy.setColumnMapping(columnMappingMap); strategy.setType(User.class); CsvToBean<User> csvToBean = new CsvToBeanBuilder<User>(reader) .withMappingStrategy(strategy) .withFilter(new MyCsvToBeanFilter()) .withIgnoreField(User2.class, User2.class.getField("userId"))// 忽略u(píng)serId屬性 .build(); List<User> list = csvToBean.parse(); for (User user : list) { System.out.println(JSON.toJSONString(user)); } reader.close(); }
控制臺(tái)日志:
{"sex":"男","userName":"張三"} {"sex":"女","userName":"翠花"}
3. commons-csv
4. hutool CsvUtil(擴(kuò)展)
總結(jié)
到此這篇關(guān)于Java中csv文件讀寫超詳細(xì)分析的文章就介紹到這了,更多相關(guān)Java csv文件讀寫內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot對(duì)Filter過(guò)濾器中的異常進(jìn)行全局處理方案詳解
這篇文章主要介紹了SpringBoot對(duì)Filter過(guò)濾器中的異常進(jìn)行全局處理,在SpringBoot中我們通過(guò) @ControllerAdvice 注解和 @ExceptionHandler注解注冊(cè)了全局異常處理器,需要的朋友可以參考下2023-09-09Java實(shí)現(xiàn)駝峰與下劃線互轉(zhuǎn)的方法
這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)駝峰與下劃線互轉(zhuǎn)的方法,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2024-04-04Java中g(shù)etSuperclass()方法的使用與原理解讀
文章介紹了Java中的getSuperclass()方法,該方法用于獲取一個(gè)類的直接父類,通過(guò)理解其使用方式、工作原理以及實(shí)際應(yīng)用場(chǎng)景,可以更好地利用反射機(jī)制處理類的繼承關(guān)系,實(shí)現(xiàn)動(dòng)態(tài)類型檢查、類加載以及序列化等功能2025-01-01SpringBoot整合mybatis使用Druid做連接池的方式
這篇文章主要介紹了SpringBoot整合mybatis使用Druid做連接池的方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08SpringBoot如何監(jiān)聽(tīng)redis?Key變化事件案例詳解
項(xiàng)目中需要監(jiān)聽(tīng)redis的一些事件比如鍵刪除,修改,過(guò)期等,下面這篇文章主要給大家介紹了關(guān)于SpringBoot如何監(jiān)聽(tīng)redis?Key變化事件的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08Java Swing JCheckBox復(fù)選框的實(shí)現(xiàn)方法
這篇文章主要介紹了Java Swing JCheckBox復(fù)選框的實(shí)現(xiàn)方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-12-12Java經(jīng)典設(shè)計(jì)模式之責(zé)任鏈模式原理與用法詳解
這篇文章主要介紹了Java經(jīng)典設(shè)計(jì)模式之責(zé)任鏈模式,簡(jiǎn)單說(shuō)明了責(zé)任鏈模式的概念、原理,并結(jié)合實(shí)例形式分析了java實(shí)現(xiàn)責(zé)任鏈模式的具體用法與相關(guān)注意事項(xiàng),需要的朋友可以參考下2017-08-08