java中csv文件读写分析(代码片段)

骑个小蜗牛 骑个小蜗牛     2023-04-03     766

关键词:

文章目录


一、txt、csv、tsv文件

txt、csv、tsv都属于文本文件

文件类型英文全称名称分隔符描述
txttext文本类型没有明确要求可以有分隔符,也可以没有
csvComma-separated values逗号分隔值类型半角逗号:','csv是txt的特殊类型
tsvTab-separated values制表符分隔值制表符:'\\t'tsv是txt的特殊类型

csv又有叫做Char-separated values(字符分隔值类型),通过字符值进行分隔。

但因为半角逗号在数据中出现的的可能性比较大,所以经常会使用文本包装符来标识逗号为数据中的一部分,或者直接使用其它特殊符号作为分隔符。

二、csv文件规范

  1. 每一行记录位于一个单独的行上,用回车换行符CRLF(\\r\\n)分割。
  2. 文件中的最后一行记录可以有结尾回车换行符,也可以没有。
  3. 第一行可以存在一个可选的标题头,格式和普通记录行的格式一样。标题头要包含文件记录字段对应的名称,应该有和记录字段一样的数量。
  4. 在标题头行和普通行每行记录中,会存在一个或多个由半角逗号(,)分隔的字段。整个文件中每行应包含相同数量的字段,空格也是字段的一部分,不应被忽略。每一行记录最后一个字段后不能跟逗号。(通常用逗号分隔,也有其他字符分隔的CSV,需事先约定)
  5. 每个字段可用也可不用半角双引号(")(文本包装符)括起来(如Microsoft的Excel就根本不用双引号)。如果字段没有用引号括起来,那么该字段内部不能出现双引号字符。
  6. 字段中若包含回车换行符、双引号或者逗号,该字段需要用双引号括起来。
  7. 如果用双引号括字段,那么出现在字段内的双引号前必须再加一个双引号进行转义。

三、csv使用场景

csv文件经常用于导出大批量数据(csv比excel更轻量级,更适合大批量数据)。

csv与excel对比:

  • csv只能用于存储纯文本内容,excel不仅支持纯文本内容还支持二进制数据
  • csv可以看做是excel的轻量级简单版实现,excel比csv更加强大
  • csv文件可以被excel软件直接打开,csv文件一般用于表格数据的传输

四、Java中的csv类库

java中的csv的类库主要有以下几类:

  • javacsv:javacsv在2014-12-10就不维护了
  • opencsv:opencsv是apache的项目,至今仍在维护

1. javacsv

2. opencsv

opencsv是一个用Java来分析和生成csv文件的框架。通常用来bean的写入csv文件和从csv文件读出bean,并支持注解的方式。

maven依赖:

<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>5.6</version>
</dependency>

写入器

名称描述
CSVWriter简单的CSV写入器
CSVParserWriter通过CSVParser解析数据的写入器
StatefulBeanToCsv直接将bean写入CSV的写入器

读取器

名称描述
CSVReader简单的CSV读取器
CsvToBeanCSV读取为bean的读取器
CSVReaderHeaderAware

解析器

名称描述
CSVParser简单的CSV解析器
RFC4180Parser基于RFC4180规范的解析器

注解

注解描述主要属性
@CsvBindByName按表头名称绑定required:必须字段,默认为false.该字段为空抛异常
column:对象列标题名称
@CsvBindByPosition按位置绑定required:必须字段,默认为false.该字段为空抛异常
position:位置索引
@CsvCustomBindByName与CsvBindByName相同,但必须提供自己的数据转换类required:必须字段,默认为false.该字段为空抛异常
column:对象列标题名称
converter:转换器
@CsvCustomBindByPosition与CsvBindByPosition相同,但必须提供自己的数据转换类required:必须字段,默认为false.该字段为空抛异常
column:对象列标题名称
converter:转换器
@CsvBindAndJoinByName应用于MultiValuedMap集合类型的bean字段,通过标题名称绑定required:必须字段,默认为false.该字段为空抛异常
column:对象列标题名称
converter:转换器
mapType:集合类型
elementTyp:元素类型
@CsvBindAndJoinByPosition应用于MultiValuedMap集合类型的bean字段,通过位置索引绑定required:必须字段,默认为false.该字段为空抛异常
position:位置索引
converter:转换器
mapType:集合类型
elementTyp:元素类型
@CsvBindAndSplitByName应用于Collection集合类型的bean字段,通过标题名称绑定required:必须字段,默认为false.该字段为空抛异常
column:对象列标题名称
converter:转换器
mapType:集合类型
elementTyp:元素类型
splitOn:
@CsvBindAndSplitByPosition应用于Collection集合类型的bean字段,通过位置索引绑定required:必须字段,默认为false.该字段为空抛异常
position:位置索引
converter:转换器
mapType:集合类型
elementTyp:元素类型
splitOn:
@CsvDate应用于日期/时间类型的bean字段,与上面相关的绑定注解结合使用value:日期格式,例如:yyyy-MM-dd
@CsvNumber应用于数字类型的bean字段,与上面相关的绑定注解结合使用value:数字格式,例如:000.###

映射策略

名称描述重要方法方法描述
ColumnPositionMappingStrategy列位置映射策略,用于没有头文件(标题行)的文件setColumnMapping(String… columnMapping设置要映射的列名集合,集合下标即为列写入顺序
HeaderColumnNameMappingStrategy标题列名称映射策略,setColumnOrderOnWrite(Comparator writeOrder)通过比较器,设置列写入顺序
HeaderColumnNameTranslateMappingStrategy标题列名称翻译映射策略
bean的属性名可以与csv列头不一样,通过指定map来映射。
setColumnMapping(Map<String, String> columnMapping)设置标题名与列名的映射
FuzzyMappingStrategy

① ColumnPositionMappingStrategy

使用该映射策略需要csv文件没有标题行。该策略通过设置列的下标位置来指定列的顺序,有两种方式来设置列的下标:

  • 通过CsvBindByPosition、CsvCustomBindByPosition、CsvBindAndJoinByPosition、CsvBindAndSplitByPosition注解来设置列的下标
  • 通过setColumnMapping(String… columnMapping)方法来设置列的下标

② HeaderColumnNameMappingStrategy

该映射策略用于有标题行的csv文件。该策略通过指定比较器来指定列的顺序:

  • 通过setColumnOrderOnWrite(Comparator writeOrder)指定比较器

关于标题列的名称:

  • 默认使用bean的字段名称大写作为标题列的名称
  • 如果使用CsvBindByName、CsvCustomBindByName、CsvBindAndJoinByName、CsvBindAndSplitByName注解的column属性指定列名称,则使用该值,否则使用bean的字段名称大写作为标题列的名称

③ HeaderColumnNameTranslateMappingStrategy

该映射策略用于有标题行的csv文件。该策略通过映射Map来指定标题列名与bean的属性名映射关系。

映射Map的key=标题列名,value=bean的属性名。

需要注意:

  • 该映射策略只适用于读取csv文件时,指定标题列名与bean的属性名的映射关系
  • 该映射策略不适用于写入csv文件时,指定bean的属性名与标题列名的映射关系(不要误解)

过滤器

名称描述
CsvToBeanFilter读取时根据过滤规则过滤掉一些行

主要方法:boolean allowLine(String[] line)

  • 入参中的line表示一行数据的集合
  • 返回值为false的这行数据被将被过滤掉

构建器

名称描述
CSVWriterBuilderCSV写入构建器,构建CSVWriter或CSVParserWriter
StatefulBeanToCsvBuilder对象写入CSV构建器,构建StatefulBeanToCsv
CSVReaderBuilderCSV读取构建器,构建CSVReader
CsvToBeanBuilderCSV读取对象构建器,构建CsvToBean
CSVReaderHeaderAwareBuilder构建CSVReaderHeaderAware
CSVParserBuilderCSV解析器构造器,构建CSVParser
RFC4180ParserBuilderRFC4180解析器构造器,构建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;

① 简单的写入

CSVWriter的主要参数:

  • Writer writer:指定需要写入的源文件

  • char separator:分隔符(默认逗号)

  • char quotechar:文本边界符(默认双引号)

    如果数据中包含分隔符,需要使用文本边界符包裹数据。通常用双引号、单引号或斜杠作为文本边界符

  • char escapechar:转义字符(默认双引号)

  • String lineend:行分隔符(默认为\\n)

使用方法:

    /**
     * 简单的写入
     * @throws Exception
     */
    private static void csvWriter() throws Exception 
        // 写入位置
        String classpath = Thread.currentThread().getContextClassLoader().getResource("").getPath();
        String fileName = classpath+"test/demo.csv";
        // 标题行
        String[] titleRow = "用户ID", "用户名", "性别";
        // 数据行
        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. 通过new CSVWriter对象的方式直接创建CSVWriter对象
        // CSVWriter csvWriter = new CSVWriter(writer);
        // 2. 通过CSVWriterBuilder构造器构建CSVWriter对象
        CSVWriter csvWriter = (CSVWriter) new CSVWriterBuilder(writer)
                .build();
        // 写入标题行
        csvWriter.writeNext(titleRow, false);
        // 写入数据行
        csvWriter.writeAll(dataRows, false);
        csvWriter.close();
    

demo.csv内容:

用户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);
        // 如果需要标题行,可这样写入
        // 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内容:

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"));

        // 如果需要标题行,可这样写入
        // 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内容:

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"));
        // 可通过比较器指定列的顺序
        // 标题行的列名默认为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内容:

USERID,SEX,USERNAME
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"));
        // 可通过比较器指定列的顺序
        // 通过CsvBindByName注解的column属性,指定标题行的列名
        HeaderColumnNameMappingStrategy<User2> strategy = new HeaderColumnNameMappingStrategy<>();
        // 注意这里的key是指的标题行的列名
        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)
                .withApplyQuotes

csv文件的读写(代码片段)

1.csv文件分隔符:一般常用的是‘,‘(逗号分隔符)。但是有些CSV文件需要存储文章句子信息等,这些信息‘,‘符是常用字符,容易造成解析出错或者解析方法复杂。可以选用‘^‘/‘ ‘等不常用的字符作为分隔符。应用途而... 查看详情

利用javacsv实现java读写csv文件(代码片段)

今天跟大家分享一个利用外部Jar包来实现Java操作CSV文件一.资源下载1.直接下载Jar包:http://central.maven.org/maven2/net/sourceforge/javacsv/javacsv/2.0/javacsv-2.0.jar2.利用Maven下载Jar包:<dependency><groupId>net.so 查看详情

java中excel文件解析总结以及超大文件读写的分析报告(代码片段)

...系统与系统之间进行数据传递时,经常需要使用Excel文件来进行数据的导入或者导出。因此,在Java语言实现这类需求时,往往会面临着数据的导入(解析)或者导出(生成)。Java中可以用来处理Excel文件的主流技术主要包... 查看详情

基于java注解的csv读写框架更加简单灵活(代码片段)

...两个框架提供的特性都非常的基础。创作原由以前觉得csv文件的读写非常简单,就懒得封装。最近一个月写了两次csv文件相关的东西,发现要处理的细节还是有的,还浪费比较多的时间。比如:UTF-8中文编码使用excel打开乱码,... 查看详情

pandas数据分析(代码片段)

...tail(2)1213#sample(n)从数据中随机采样得到n个样本14df.sample(2)文件读写  Pandas提供了读取不同格式文件的接口1#在读取文件的时候,有许多必要的参数需要指定,以便得到的数据可以直接用于后续的数据分析2#分块读取3chunker=pd.read_... 查看详情

读写csv文件(代码片段)

这是已存在的一个csv文件importospath=os.getcwd()+‘\\‘#获取当前路径print(path)withopen(path+‘aaa.csv‘,‘r‘,newline=‘‘)asfilereader:#读取已有文件withopen(path+‘bbb.csv‘,‘w‘,newline=‘‘)asfilewriter:#写入一个新文件header=filereader.rea 查看详情

详解pandas的read_csv()(代码片段)

...用Pandas处理数据的第一步往往就是读入数据,比如读写CSV文件,而Pandas也提供了强劲的读取支持,参数有38个之多。这些参数中,有的容易被忽略,但却在实际工作中用处很大。比如:文件读取时设置某些列为时间类型导入文件... 查看详情

python数据分析(代码片段)

...#xff01;!!pandas库(四)数据加载、存储与文件格式读写文本格式文件直接使用read_csv方法进行读取df=pd.read_csv('ex.csv')使用read_table方法进行读取,需要指定分隔符pd.read_tabl 查看详情

python数据分析(代码片段)

...#xff01;!!pandas库(四)数据加载、存储与文件格式读写文本格式文件直接使用read_csv方法进行读取df=pd.read_csv('ex.csv')使用read_table方法进行读取,需要指定分隔符pd.read_tabl 查看详情

使用commons-csv简单读写csv文件(代码片段)

...试环境将做迁移。因此需要对zookeeper上的重要的数据以CSV文件格式做备份。本文通过Apache的commons-csv操作CSV文件。官网地址:http://commons.apache.org/proper/commons-csv/基本概念维基百科对CSV的解释:逗号分隔值(Comma-SeparatedValues,CSV,... 查看详情

数据读写csv文件与xls/xlsx文件(代码片段)

目录一、csv格式与xls/xlsx格式的区别二、两种文件格式的读写操作1.csv文件的读/写函数csvreadcsvwrite2.xls/xlsx文件的读/写函数xlsreadxlswrite三、应用案例1.实例1参考资料一、csv格式与xls/xlsx格式的区别csv格式与xls/xlsx格式的文件在样式... 查看详情

python读取csv文件做dbscan分析(代码片段)

1.读取csv数据做dbscan分析读取csv文件中相应的列,然后进行转化,处理为本算法需要的格式,然后进行dbscan运算,目前公开的代码也比较多,本文根据公开代码修改,具体代码如下:fromsklearnimportdatasetsi... 查看详情

#littlefs原理分析#[五]文件读写(代码片段)

...了littlefs中的目录操作,这一篇文章则将介绍littlefs中的文件读写操作。本文会根据文件的存储类型进行介绍,即inline文件和outline文件,其读写过程也有差别。另外还会介绍inline文件到outline文件的转换,以及littlefs底层的读写API... 查看详情

java将内容写入到csv文件中(代码片段)

首先需要在pom文件中引入opencsv的jar包<!--csv--><dependency><groupId>com.opencsv</groupId><artifactId>opencsv</artifactId> 查看详情

csv读写数据(代码片段)

对于CSV数据的读写比较简单。一。读取数据第一种:导入importcsv1withopen(‘abc.csv‘,‘r‘)ascsvfile:2reader=csv.reader(csvfile)3forxinreader:4print(x)此种方法读取的每行数据在一个列表中。第二种:导入importcsv1withopen(‘abc.csv‘,‘r‘)ascsvfile:2... 查看详情

小计:协同办公衍生出的需求(代码片段)

...在线office来协同办公,然后所有的在线文档会有一份本地文件用来存储和数据分析1.2.需求需求是这样的:希望企业系统和文职人员以及分析部能够共同管理这些Excel表格,但不想耗费资源去开发OA之类的系统,希望开发部想办法... 查看详情

csv-03-csv读写框架支持数组mapcollection等常见集合(代码片段)

集合类有时候对象中会包含数组、Map、Collection等常见集合。为了存储的便利性,默认提供集合的相关支持。特性和普通字段保持一致,如果指定注解转换,则以注解为准。使用示例UserCollection.java用于演示集合的对象publicclassUserC... 查看详情

超详解python读写csv文件及空行问题解决(代码片段)

Python操作csv文件1.What'sCSV2.WriteCSV2.1list2.2dict3.ReadCSV3.1list3.2dict4.CSV空行问题解决4.1Python2解决4.2Python3解决1.What’sCSVCSV:逗号分隔值(Comma-SeparatedValues,CSV,也称为字符分隔值, 查看详情