Java实现CSV文件的读写(包含追加内容)

本文介绍了如何使用Java处理CSV文件,包括文件的读取、写入和追加内容。通过Apache Commons Lang3库的BufferedWriter实现文件操作,详细展示了相关代码示例并进行了测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

  逗号分隔值(Comma-Separated Values,CSV,有时也称为字符分隔值,因为分隔字符也可以不是逗号),其文件以纯文本形式存储表格数据(数字和文本)。纯文本意味着该文件是一个字符序列,不含必须像二进制数字那样被解读的数据,CSV文件的特点:

  • 文件由任意数目的记录组成
  • 每条记录由字段组成,字段间的分隔符是其它字符或字符串,最常见的是逗号或制表符
  • 记录间以某种换行符分隔(windows和linux下不一样)
  • 所有记录都有完全相同的字段序列
  • 通常都是纯文本文件(一般是建议使用文本编辑工具打开)

二、maven依赖或jar

   <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
       <version>3.12.0</version>
   </dependency>
   
   <dependency>
       <groupId>junit</groupId>
       <artifactId>junit</artifactId>
       <version>4.12</version>
       <scope>compile</scope>
   </dependency>

  如果你没有使用maven工程,你也可去去下载相关jar包比如: commons-lang3-3.12.0.jar,效果是一样的, junit 只是用于单元测试.

三、CSV工具类

CsvUtil.java

package com.alian.csdn.utils;

import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class CsvUtil {

    /**
     * CSV文件生成方法  字符流追加:FileWriter writer = new FileWriter(file,true)
     *
     * @param headLabel 头部标签
     * @param dataList  数据列表
     * @param filePath  文件路径
     * @param addFlag   是否追加
     */
    public static void writeToCsv(String headLabel, List<String> dataList, String filePath, boolean addFlag) {
        BufferedWriter buffWriter = null;
        try {
            //根据指定路径构建文件对象
            File csvFile = new File(filePath);
            //文件输出流对象,第二个参数时boolean类型,为true表示文件追加(在已有的文件中追加内容)
            FileWriter writer = new FileWriter(csvFile, addFlag);
            //构建缓存字符输出流(不推荐使用OutputStreamWriter)
            buffWriter = new BufferedWriter(writer, 1024);
            //头部不为空则写入头部,并且换行
            if (StringUtils.isNotBlank(headLabel)) {
                buffWriter.write(headLabel);
                buffWriter.newLine();
            }
            //遍历list
            for (String rowStr : dataList) {
                //如果数据不为空,则写入文件内容,并且换行
                if (StringUtils.isNotBlank(rowStr)) {
                    buffWriter.write(rowStr);
                    buffWriter.newLine();//文件写完最后一个换行不用处理
                }
            }
            //刷新流,也就是把缓存中剩余的内容输出到文件
            buffWriter.flush();
        } catch (Exception e) {
            System.out.println("写入csv出现异常");
            e.printStackTrace();
        } finally {
            try {
                //关闭流
                if (buffWriter != null) {
                    buffWriter.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据文件路径读取csv文件的内容
     *
     * @param filePath
     * @return
     */
    public static List<String> readFromCsv(String filePath) {
        ArrayList<String> dataList = new ArrayList<>();
        BufferedReader buffReader = null;
        try {
            //构建文件对象
            File csvFile = new File(filePath);
            //判断文件是否存在
            if (!csvFile.exists()) {
                System.out.println("文件不存在");
                return dataList;
            }
            //构建字符输入流
            FileReader fileReader = new FileReader(csvFile);
            //构建缓存字符输入流
            buffReader = new BufferedReader(fileReader);
            String line = "";
            //根据合适的换行符来读取一行数据,赋值给line
            while ((line = buffReader.readLine()) != null) {
                if (StringUtils.isNotBlank(line)) {
                    //数据不为空则加入列表
                    dataList.add(line);
                }
            }
        } catch (Exception e) {
            System.out.println("读取csv文件发生异常");
            e.printStackTrace();
        } finally {
            try {
                //关闭流
                if (buffReader != null) {
                    buffReader.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return dataList;
    }

}

  这里需要注意的是文件输出流对象,第二个参数时boolean类型,为true表示文件追加(在已有的文件中追加内容)

     FileWriter writer = new FileWriter(csvFile, addFlag);

  关于BufferedWriter使用几点说明:

  • 使用到的是缓存字符输出流,默认大小是8192,我这里使用的是1024
  • 没有进行流的关闭操作,数据会存在缓冲区中,不会存储到文件上,只有当数据超过了缓冲区的大小(比如这里的1024),或者手动调用flush方法,数据才会刷新到文件上
  • 调用close方法的内部会先调用flush刷新缓冲区

关于流的更多内容可以参考:Java中常见IO流的介绍与使用

四、CSV读写测试

4.1、文件写入

    @Test
    public void writeToCsv() {
        String headDataStr = "交易流水,商户编号,订单金额,支付金额,优惠金额,收款账户,支付方式,支付状态,支付时间,交易类型";
        String csvfile = "C:\\myFile\\CSV\\对账文件20211111.csv";
        List<String> dataList = new ArrayList<>();
        dataList.add("190469644375,100011,4000,4000,0,105000041112608,03,00,2021-09-12 07:44:12,8");
        dataList.add("190469644954,100011,4000,4000,0,105000041112608,03,00,2021-09-12 07:50:10,8");
        dataList.add("190469645620,100011,4000,4000,0,105000041112608,03,00,2021-09-12 07:56:59,8");
        dataList.add("190469661593,100011,2000,2000,0,105000041112608,01,00,2021-09-12 09:51:24,8");
        dataList.add("190469661738,100011,2000,2000,0,105000041112608,01,00,2021-09-12 09:52:15,8");
        dataList.add("190469661853,100011,2000,2000,0,105000041112608,01,00,2021-09-12 09:52:51,8");
        dataList.add("190469661931,100011,2000,2000,0,105000041112608,01,00,2021-09-12 09:53:27,8");
        dataList.add("190469699471,100011,2000,2000,0,105000041112608,03,00,2021-09-12 13:59:02,8");
        dataList.add("190469699540,100011,2000,2000,0,105000041112608,03,00,2021-09-12 13:59:29,8");
        dataList.add("190469712840,100011,4000,4000,0,105000041112608,03,00,2021-09-12 15:20:32,8");
        CsvUtil.writeToCsv(headDataStr, dataList, csvfile, false);
    }

运行结果:
我这里使用notepad++工具打开,查看到内容如下:
在这里插入图片描述

4.2、文件内容追加

    @Test
    public void appendToCsv() {
        String csvfile = "C:\\myFile\\CSV\\对账文件20211111.csv";
        List<String> dataList = new ArrayList<>();
        dataList.add("190469730006,100011,4000,4000,0,105000041112608,01,00,2021-09-12 16:52:57,8");
        dataList.add("190469730173,100011,4000,4000,0,105000041112608,01,00,2021-09-12 16:53:54,8");
        dataList.add("190469730367,100011,4000,4000,0,105000041112608,01,00,2021-09-12 16:54:50,8");
        dataList.add("190469736543,100011,4000,4000,0,105000041112608,01,00,2021-09-12 17:25:53,8");
        dataList.add("190469746558,100011,4000,4000,0,105000041112608,01,00,2021-09-12 18:14:13,8");
        CsvUtil.writeToCsv("", dataList, csvfile, true);
    }

运行结果:
我这里使用notepad++工具打开,查看到在原有内容的基础上增加了内容
在这里插入图片描述

4.3、文件读取

    @Test
    public void readFromCsv() {
        String csvFilePath = "C:\\myFile\\CSV\\对账文件20211111.csv";
        List<String> list = CsvUtil.readFromCsv(csvFilePath);
        for (String data : list) {
            System.out.println(data);
        }
    }

运行结果:

交易流水,商户编号,订单金额,支付金额,优惠金额,收款账户,支付方式,支付状态,支付时间,交易类型
190469644375,100011,4000,4000,0,105000041112608,03,00,2021-09-12 07:44:12,8
190469644954,100011,4000,4000,0,105000041112608,03,00,2021-09-12 07:50:10,8
190469645620,100011,4000,4000,0,105000041112608,03,00,2021-09-12 07:56:59,8
190469661593,100011,2000,2000,0,105000041112608,01,00,2021-09-12 09:51:24,8
190469661738,100011,2000,2000,0,105000041112608,01,00,2021-09-12 09:52:15,8
190469661853,100011,2000,2000,0,105000041112608,01,00,2021-09-12 09:52:51,8
190469661931,100011,2000,2000,0,105000041112608,01,00,2021-09-12 09:53:27,8
190469699471,100011,2000,2000,0,105000041112608,03,00,2021-09-12 13:59:02,8
190469699540,100011,2000,2000,0,105000041112608,03,00,2021-09-12 13:59:29,8
190469712840,100011,4000,4000,0,105000041112608,03,00,2021-09-12 15:20:32,8
190469730006,100011,4000,4000,0,105000041112608,01,00,2021-09-12 16:52:57,8
190469730173,100011,4000,4000,0,105000041112608,01,00,2021-09-12 16:53:54,8
190469730367,100011,4000,4000,0,105000041112608,01,00,2021-09-12 16:54:50,8
190469736543,100011,4000,4000,0,105000041112608,01,00,2021-09-12 17:25:53,8
190469746558,100011,4000,4000,0,105000041112608,01,00,2021-09-12 18:14:13,8

结语

  其实这个工具不仅仅是用于CSV文件的操作,其他的字符流的文件都是可以进行读写的。

### Java 读写 CSV 文件 #### 使用 Apache Commons CSV 库来实现 为了简化CSV文件的操作,在Java项目中可以引入Apache Commons CSV库。此库提供了方便的方法来进行CSV文件的解析和创建。 对于Maven构建工具管理的项目,可以在`pom.xml`文件里加入如下依赖声明[^3]: ```xml <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-csv</artifactId> <version>1.10.0</version> </dependency> ``` 下面展示一段简单的例子程序,该程序能够完成向指定路径下的CSV文件追加记录以及从给定位置加载并打印所有条目: #### 写入CSV文件 通过使用`FileWriter`类配合`BufferedWriter`对象可实现在磁盘上保存新的CSV文档或更新已有的文档内容。这里给出了一种方式来把列表中的数据序列化成CSV格式字符串再写出到目标文件之中[^2]。 ```java import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; import java.io.FileWriter; import java.io.IOException; import java.util.List; public class CsvWriteExample { public static void writeCsvFile(List<List<String>> dataList, String outputPath, String fileName) throws IOException { try (CSVPrinter printer = new CSVPrinter(new FileWriter(outputPath + "/" + fileName), CSVFormat.DEFAULT)) { for (List<String> row : dataList) { printer.printRecord(row); } } catch (IOException e) { throw new RuntimeException(e); } } } ``` 这段代码定义了一个名为`writeCsvFile`的方法接收三个参数:一个是包含多行记录的数据集合;另外两个分别是输出目录地址与待生成/修改的目标文件名称。它利用了try-with-resources语句自动关闭资源特性确保即使发生异常也能正确释放占用资源[^4]。 #### 读取CSV文件 当需要获取存储于本地系统的CSV资料时,则可以通过`CSVParser`接口所提供的功能轻松达成目的。下面是一段用来遍历整个输入流并将每一行转换为String数组形式返回的例子[^1]。 ```java import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVParser; import org.apache.commons.csv.CSVRecord; import java.io.FileReader; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; public class CsvReadExample { private static List<List<String>> readCsv(String filePath) throws IOException { List<List<String>> records = new ArrayList<>(); try (CSVParser parser = CSVParser.parse(Files.newBufferedReader(Paths.get(filePath)), CSVFormat.DEFAULT.withFirstRecordAsHeader())) { for (CSVRecord record : parser) { List<String> lineData = new ArrayList<>(record.size()); for (int i = 0; i < record.size(); ++i){ lineData.add(record.get(i)); } records.add(lineData); } } return records; } } ``` 上述函数实现了基本的功能——打开指定路径处存在的CSV文档,并逐行扫描直至结束为止。每遇到一行有效信息就将其分割开来存放到临时容器内最后统一打包送回调用者那里进一步处理。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值