< groupId > org.apache.commons </ groupId > < artifactId > commons-csv </ artifactId > < version > 1.7 </ version > </ dependency >

我把CSV的上传、下载、解析、写入的通用方法,都整合在了CSVUtils类中。

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
 * @Author: Denebola
 * @Date: 2019/7/18-16:48
 * @Description: CSV工具类
public class CSVUtils {
    private static Logger logger = LoggerFactory.getLogger(CSVUtils.class);
    //行尾分隔符定义
    private final static String NEW_LINE_SEPARATOR = "\n";
    //上传文件的存储位置
    private final static URL PATH = Thread.currentThread().getContextClassLoader().getResource("");
     * @return File
     * @Description 创建CSV文件
     * @Param fileName 文件名,head 表头,values 表体
    public static File makeTempCSV(String fileName, String[] head, List<String[]> values) throws IOException {
//        创建文件
        File file = File.createTempFile(fileName, ".csv", new File(PATH.getPath()));
        CSVFormat formator = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR);
        BufferedWriter bufferedWriter =
                new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), "UTF-8"));
        CSVPrinter printer = new CSVPrinter(bufferedWriter, formator);
//        写入表头
        printer.printRecord(head);
//        写入内容
        for (String[] value : values) {
            printer.printRecord(value);
        printer.close();
        bufferedWriter.close();
        return file;
     * @return boolean 
     * @Description 下载文件
     * @Param response,file
    public static boolean downloadFile(HttpServletResponse response, File file) {
        FileInputStream fileInputStream = null;
        BufferedInputStream bufferedInputStream = null;
        OutputStream os = null;
        try {
            fileInputStream = new FileInputStream(file);
            bufferedInputStream = new BufferedInputStream(fileInputStream);
            os = response.getOutputStream();
            //MS产本头部需要插入BOM
            //如果不写入这几个字节,会导致用Excel打开时,中文显示乱码
            os.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});
            byte[] buffer = new byte[1024];
            int i = bufferedInputStream.read(buffer);
            while (i != -1) {
                os.write(buffer, 0, i);
                i = bufferedInputStream.read(buffer);
            return true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
        	//关闭流
            if (os != null) {
                try {
                    os.flush();
                    os.close();
                } catch (IOException e) {
                    e.printStackTrace();
            if (bufferedInputStream != null) {
                try {
                    bufferedInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                }




    
 catch (IOException e) {
                    e.printStackTrace();
            file.delete();
        return false;
     * @return File
     * @Description 上传文件
     * @Param multipartFile
    public static File uploadFile(MultipartFile multipartFile) {
        String path = PATH.getPath() + multipartFile.getOriginalFilename();
        try {
            File file = new File(path);
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            multipartFile.transferTo(file);
            logger.info("上传文件成功,文件名===>" + multipartFile.getOriginalFilename() + ", 路径===>" + file.getPath());
            return file;
        } catch (IOException e) {
            logger.error("上传文件失败" + e.getMessage(), e);
            return null;
     * @return List<List<String>>
     * @Description 读取CSV文件的内容(不含表头)
     * @Param filePath 文件存储路径,colNum 列数
    public static List<List<String>> readCSV(String filePath, int colNum) {
        BufferedReader bufferedReader = null;
        InputStreamReader inputStreamReader = null;
        FileInputStream fileInputStream = null;
        try {
            fileInputStream = new FileInputStream(filePath);
            inputStreamReader = new InputStreamReader(fileInputStream);
            bufferedReader = new BufferedReader(inputStreamReader);
            CSVParser parser = CSVFormat.DEFAULT.parse(bufferedReader);
//          表内容集合,外层List为行的集合,内层List为字段集合
            List<List<String>> values = new ArrayList<>();
            int rowIndex = 0;
            for (CSVRecord record : parser.getRecords()) {
//              跳过表头
                if (rowIndex == 0) {
                    rowIndex++;
                    continue;
//              每行的内容
                List<String> value = new ArrayList<>(colNum + 1);
                for (int i = 0; i < colNum; i++) {
                    value.add(record.get(i));
                values.add(value);
                rowIndex++;
            return values;
        } catch (IOException e) {
            logger.error("解析CSV内容失败" + e.getMessage(), e);
        }finally {
        	//关闭流
            if (bufferedReader != null) {
                try {
                    bufferedReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
            if (inputStreamReader != null) {
                try {
                    inputStreamReader.close();
                } catch (IOException e) {
                    e.printStackTrace();
            if (fileInputStream != null) {
                try {
                    fileInputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
        return null;

Controller.java

import com.denebola.learnspringboot.CSVUtils;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.List;
@Slf4j
@RestController
public class Controller {
    private static Logger logger = LoggerFactory.getLogger(Controller.class);
	//定义自己的服务类接口
    @Autowired
    private Service service;
     * @param response
     * @return
     * @Description 下载CSV
    @GetMapping("/downloadAll")
    public String downloadAllUserRoleCSV(HttpServletResponse response) {
        String[] head = service.getHead();
        List<String[]> values = service.getValues();
        String fileName = service.getName();
        File file = CSVUtils.makeTempCSV(fileName, head, values);
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition", "attachment;fileName=" + fileName +".csv");
        CSVUtils.downloadFile(response, file);
        return null;
     * @return
     * @Description 上传CSV
     * @Param file
    @PostMapping(value = "/upload")
    public String upload(@RequestParam("file") MultipartFile multipartFile) {
        try {
        	//上传内容不能为空
            if (multipartFile.isEmpty()) {
                return "500";
            File file = CSVUtils.uploadFile(multipartFile);
            List<List<String>> userRoleLists = CSVUtils.readCSV(file.getPath(), 2);
            service.doSth(userRoleLists);
            file.delete();
            return "200";
        } catch (Exception e) {
            e.printStackTrace();
        return "500";

需要值得注意的是,在使用Java生成CSV文件时,可能出现中文乱码的问题,这是由于微软的产品为了检测一个字节流是否是UTF-8编码,而添加了BOM标记。而有的文本编辑软件,比如Notepad、VScode、记事本等,不会做这种检测,会当作正常字符处理。所以产生的现象就是,Excel打开是乱码时,记事本打开不是乱码。

为了解决这种问题,我们可以手动的加入BOM。上述代码中添加的方式是os.write(new byte[]{(byte) 0xEF, (byte) 0xBB, (byte) 0xBF});,如果不使用Response的out进行输出的话,可以改用以下代码:

OutputStreamWriter osw = new OutputStreamWriter(resp.getOutputStream(), "UTF-8"); 
osw.write(new String(new byte[] { (byte) 0xEF, (byte) 0xBB,(byte) 0xBF }));   
                    工作中遇到了将所有数据整合成CSV文件并下载、上传CSV文件并解析,这两个需求。现在把处理方法记录下来,作为总结。项目构建jar包引入CSV的解析和写入使用到的是commons-csv的包,pom中的定义如下        &lt;dependency&gt;            &lt;groupId&gt;org.apache.commons&lt;/groupId&gt;   ...
				
赠送jar包:seata-spring-boot-starter-1.3.0.jar; 赠送原API文档:seata-spring-boot-starter-1.3.0-javadoc.jar; 赠送源代码:seata-spring-boot-starter-1.3.0-sources.jar; 赠送Maven依赖信息文件:seata-spring-boot-starter-1.3.0.pom; 包含翻译后的API文档:seata-spring-boot-starter-1.3.0-javadoc-API文档-中文(简体)版.zip; Maven坐标:io.seata:seata-spring-boot-starter:1.3.0; 标签:seata、spring、boot、starter、中文文档、jar包、java; 使用方法:解压翻译后的API文档,用浏览器打开“index.html”文件,即可纵览文档内容。 人性化翻译,文档中的代码和结构保持不变,注释和说明精准翻译,请放心使用。 支持TCP长连接消息转发到Spring容器 支持自定义消息枚举类( CommandController , CommandMapping ) 支持自定义通信协议解析( ProtocolProcessor ) 支持不同系统事件通知机制( EventHandler ) 使用SpringMVC中RestController的CommandController和GetMapping的CommandMapping进行消息定义,系统会自动将其注册进系统里 @CommandController public class SimpleCommand { @Autowired private SimpleService simpleService; @Comm
< dependency> < groupId>org.springframework.boot</ groupId> < artifactId>spring-boot-starter-web</ artifactId> < version>${spring-boot.version}</ version> </ dependency> spring-boot-project依赖根 spring-boot-first-application-sample演示模块 spring-boot-configuration-sample配置模块 spring-boot-import-sample导入实现模块 spring-boot-alias-annotation-sample注解属性别名模块 spring-boot-actuator-sample监控组件模块 spring-boot-enable-sample自动装配模块 formatter-spring-boot-starter-sample自定义启动模
.csv文件是什么? CSV文件最早用在简单的数据库里,由于其格式简单,并具备很强的开放性,所以起初被扫图家用作自己图集的标记。CSV文件是个纯文本文件,每一行表示一张图片的许多属性。你在收一套图集时,只要能找到它的CSV文件,用专用的软件校验后,你对该图集的状况就可以了如指掌。 每行相当于一条记录,是用“,”分割字段的纯文本数据库文件 在 java解析 来吧上代码吧 maven <dependency> <groupId>de.sieg
EasyExcel EasyExcel是一个基于Java的简单,省内存的读写Excel的开源项目。在节省存储的情况下下支持读写百M的Excel。64M内存1分钟内读取75M(46W行25列)的Excel。 ,当然还有急速模式能恢复,但是内存占用会在100M多一点 Spring Boot Stater依赖 方便在web环境下使用easyexcel ,已上传至maven仓库 < dependency> < groupId>com.pig4cloud.excel</ groupId> < artifactId>excel-spring-boot-starter</ arti
交易留言: 在框架中,对事务消息的操作越来越简单。 您只能通过注释来完成交易消息。 无论是事务消息,分布式事务解决方案还是跨平台语言解决方案,事务解决方案的核心问题是确保可以发送消息,并且消费者可以使用它们。 可靠性保证 1.添加@TransactionMessage批注,内核保证,本地事务错误,不发送消息,正确执行,发送消息,即默认提交。 2.默认情况下采用可靠性保证,并核对默认提交。 原因来自先前的因素,该因素保证本地交易不会出错。 <!-- Adding dependencies to pom. XML -->
csv文件默认编码为ANSI,这里出现乱码主要是编码不一致问题 DataInputStream in = new DataInputStream(new FileInputStream(new File("d:\\*.csv"))); BufferedReader br= new BufferedReader(new InputStreamReader(in,"GBK"));//这里如果csv
<!-- https://mvnrepository.com/artifact/com.opencsv/opencsv --> <dependency> <groupId>com.opencsv</groupId> <artifactId>opencsv</artifactId> <version>4.6</ver
mybatis-spring-boot-starter 和 spring-boot-starter-jdbc 是用于在 Spring Boot 项目中连接数据库的两个依赖包。它们有不同的功能和用途。 mybatis-spring-boot-starter 是 MyBatis 官方提供的一个 Spring Boot Starter,它包含了使用 MyBatis 进行数据库访问所需的所有依赖。通过引入 mybatis-spring-boot-starter,您可以方便地使用 MyBatis 进行数据库操作,而无需单独引入 spring-boot-starter-jdbc 。 spring-boot-starter-jdbc 是 Spring Boot 官方提供的一个 Starter,用于支持使用 JDBC 进行数据库访问。如果您不使用 MyBatis,而只是使用 Spring 的 JdbcTemplate 进行数据库操作,那么您需要引入 spring-boot-starter-jdbc 依赖。它提供了一些必要的配置和支持,使您可以方便地使用 JDBC 进行数据库访问 。 引用的内容中提到,如果您已经引入了 mybatis-spring-boot-starter,那么您不再需要单独引入 spring-boot-starter-jdbc。这是因为 mybatis-spring-boot-starter 已经包含了 spring-boot-starter-jdbc 的依赖。这样,您就可以直接使用 MyBatis 进行数据库操作,而无需关注底层的 JDBC 配置 。 总结起来,mybatis-spring-boot-starter 是用于集成 MyBatis 的 Spring Boot Starter,而 spring-boot-starter-jdbc 是用于支持使用 JDBC 进行数据库操作的 Spring Boot Starter。如果您使用 MyBatis,建议直接引入 mybatis-spring-boot-starter,它已经包含了必要的 JDBC 依赖。如果您只是使用 Spring 的 JdbcTemplate,那么需要引入 spring-boot-starter-jdbc 。