springboot将list封装成csv文件

简介: springboot将list封装成csv文件

image.png

@[toc]

一、案例描述

  • 方法1:把list封装成CSV数据文件返回file对象
  • 方法2:把list封装成CSV数据文件输出到指定文件目录

二、什么是CSV文件

image.png

三、注意点使用说明

注意点1:

CsvUtilBack是把list封装csv的工具

DateUtilBack是日期相关工具

ExportUtil是分页先关工具

注意点2:
File file = new File(pathname); 的形参pathname可以带路径path+fileName,也可以只带文件名fileName

注意点3:
封装的方法listToCsvFileSaveToDirectory中,注意往csv文件设置内容时,这里必须传string,不能传对象.toString(),否则存入的值就不对了,所以才有了先把 List转换成List的步骤,详情请看方法工具类CsvUtilBack封装的listToCsvFileSaveToDirectory方法。

四、完整代码

pom依赖

<!--导出成csv文件-->
<dependency>
    <groupId>net.sf.supercsv</groupId>
    <artifactId>super-csv</artifactId>
    <version>2.4.0</version>
</dependency>
<dependency>
    <groupId>com.github.mygreen</groupId>
    <artifactId>super-csv-annotation</artifactId>
    <version>2.1</version>
</dependency>
<dependency>
    <groupId>com.opencsv</groupId>
    <artifactId>opencsv</artifactId>
    <version>4.2</version>
</dependency>

Controller

ListToCsvController

import com.example.demo.bean.Subscriber;
import com.example.demo.util.CsvUtilBack;
import com.example.demo.util.ExportUtil;

import java.util.ArrayList;
import java.util.List;

/**
 * 测试使用把list封装成csv文件
 * @Author 211145187
 * @Date 2022/6/21 09:50
 **/
public class ListToCsvController {
   
    /**
     * 模拟使用场景描述:假设list是从数据库查出的拥有至少10w条数据的集合信息,假设pageSize是我从配置文件读出的配置信息,通过for循环就可以把10W条数据按照pageSize分成10份文件上传到服务器上,模拟的是方案2实现方式
     * 实现方案有2种:
     *      第一种:每次分页查询1W条数据 =》 封装成file上传指定服务器
     *      第二种:一次查询10W条数据 =》 通过for循环就可以把10W条数据按照pageSize分成10份文件上传到服务器上
     */
    public static void main(String[] args) {
   
        List<Subscriber> list = new ArrayList<>();
        list.add(new Subscriber(1000500, 123456, "dy1", 1, 1, 0));
        list.add(new Subscriber(1000501, 123456, "dy2", 1, 3, 0));
        list.add(new Subscriber(1000502, 123456, "dy3", 1, 5, 0));

        //假设pageSize是我从配置文件读出的配置信息
        Integer pageSize = 10000;
        Integer pageCount = ExportUtil.getPageCount(list.size(), pageSize);

        String filePath = "D:\\laji-file";
        String fileName = "userModelList";

        for(Integer pageNum = 1; pageNum < pageCount + 1; pageNum++){
   
            try {
   
                List<Subscriber> pageList = ExportUtil.getPageList(list, pageNum, pageSize, pageCount);
                List<String> fileStr = CsvUtilBack.ListToCsv(pageList);
                //调用方法1:把list封装成CSV数据文件输出到指定文件目录
                CsvUtilBack.listToCsvFileSaveToDirectory(fileStr, filePath, fileName);
                System.out.println("--ListToCsvFileSaveToDirectory-upload-success");
                //调用方法2:把list封装成CSV数据文件返回file对象
//                File file = CsvUtilBack.returnListToCsvFile(fileStr, fileName);
//                System.out.println("--returnListToCsvFile-upload-success" + file);
            } catch (Exception e) {
   
                e.printStackTrace();
                break;
            }
        }
    }
}

实体bean

Subscriber

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Subscriber implements Serializable {
   
    //序列号
    private int subscriberNumber;
    //密码
    private int Password;
    //别名
    private String subscriberAlias;
    //是否允许修改密码【0:Deny、1:Allow】
    private int changePassword;
    //用户类型【1:SIP Terminal、3:Audio/Video Recording Server、5:DC、6:Dispatch、7:Mobile Radio】
    private int subscriberType;
    //状态【0:Normal、1:Stunned、2:Kiled】
    private int status;
}

工具类

CsvUtilBack

package com.example.demo.util;

import com.github.mygreen.supercsv.annotation.CsvColumn;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;


public class CsvUtilBack {
   

    //日期:2020-07-24
    //作者:150513701
    //描述:List<T>转List<String>
    public static <T> List<String> ListToCsv(List<T> list) {
   
        if (list == null || list.isEmpty()) {
   
            return new ArrayList();
        }
        boolean first = true;
        List<String> resultList = new ArrayList<>();
        for (T t : list) {
   
            List<String> nameList = new ArrayList<>();
            List<String> valueList = new ArrayList<>();
            Field[] fields = t.getClass().getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
   
                Field field = fields[i];
                field.setAccessible(true);                                                      //这句话的目的是为了能够通过反射读取JAVA类中Private修饰的变量
                try {
   
                    Object fieldValue = field.get(t);
                    Object fieldType = field.getType();
                    if (fieldValue != null) {
   
                        if (first) {
                                                               //第一次进入函数需要获取列名
                            CsvColumn annotation = field.getAnnotation(CsvColumn.class);
                            if (annotation == null) {
   
                                nameList.add(field.getName());
                            } else {
   
                                nameList.add(annotation.label());
                            }
                        }
                        if (((Class) fieldType).getName() == "java.util.Date") {
   
                            Date date = (Date) fieldValue;
                            valueList.add(DateUtilBack.formatDate(date, "yyyy-MM-dd HH:mm:ss"));
                        } else {
   
                            valueList.add(fieldValue.toString());
                        }
                    }
                } catch (IllegalArgumentException | IllegalAccessException e) {
   
                    e.printStackTrace();
                }
            }
            //添加列头
            if (first) {
   
                resultList.add(String.join(",", nameList));
                first = false;
            }
            //添加列值
            resultList.add(String.join(",", valueList));
        }
        return resultList;
    }

    /**
     * 描述:把list封装成CSV数据文件返回file对象
     * 使用场景:方法返回csv文件,用于上传文件服务器或者上传windows路径下
     * @param list 数据集合
     * @param fileName 文件名称
     * @return File
     */
    public static File returnListToCsvFile(List<String> list, String fileName) {
   
        File csvFile = null;
        BufferedWriter csvWriter = null;

        try {
   
            csvFile = new File(fileName);
            File parent = csvFile.getParentFile();
            if (parent != null && !parent.exists()) {
   
                parent.mkdirs();
            }
            //创建文件
            csvFile.createNewFile();
            csvWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), "UTF-8"), 1024);
            //写入内容
            for (String str : list) {
   
                csvWriter.write(str);
                csvWriter.newLine();
            }
            csvWriter.flush();
        } catch (Exception e) {
   
            e.printStackTrace();
        }
        finally {
   
            try {
   
                csvWriter.close();
            } catch (IOException e) {
   
                e.printStackTrace();
            }
        }
        return csvFile;
    }

    /**
     * 描述:把list封装成CSV数据文件输出到指定文件目录
     * 使用场景:直接将csv文件上传到指定目录下
     * @param list 数据集合
     * @param fileName 文件名称
     * @param filePath 保存路径
     */
    public static void listToCsvFileSaveToDirectory(List<String> list, String filePath, String fileName) {
   
        File csvFile = null;
        BufferedWriter csvWriter = null;

        try {
   
            //创建文件
            csvFile = new File(filePath + File.separator + fileName + ".csv");
            File parent = csvFile.getParentFile();
            if (parent != null && !parent.exists()) {
   
                parent.mkdirs();
            }
            csvFile.createNewFile();
            csvWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(csvFile), "UTF-8"), 1024);
            //写入内容
            for (String str : list) {
   
                csvWriter.write(str);   //注意点1:这里必须传string,不能传对象.toString(),否则存入的值就不对了,所以才有了先把 List<Subscriber>转换成List<String>的步骤
                csvWriter.newLine();
            }
            csvWriter.flush();
        } catch (Exception e) {
   
            e.printStackTrace();
        }
        finally {
   
            try {
   
                csvWriter.close();
            } catch (IOException e) {
   
                e.printStackTrace();
            }
        }
    }
}

DateUtilBack

package com.example.demo.util;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtilBack {
   

    /**
     * 格式化日期
     *
     * @param date   日期
     * @param format 日期格式
     * @return
     */
    public static String formatDate(Date date, String format) {
   
        if (format == null || format.equals("")) {
   
            format = "yyyy-mm-dd";
        }
        if (date == null) {
   
            return "";
        } else {
   
            SimpleDateFormat df = new SimpleDateFormat(format);
            return df.format(date);
        }
    }
}

ExportUtil

package com.example.demo.util;

import java.util.List;

public class ExportUtil {
   

    /***
     * 自定义获取分页总页数的方法
     * 传参:list总数、页容量
     * 返回:总页数
     */
    public static Integer getPageCount(Integer count, Integer pageSize){
   

        Integer pageCount = 0;

        if(count.equals(0)){
   
            return pageCount;
        }

        pageCount = count/pageSize;
        if(count % pageSize != 0){
   
            pageCount++;
        }

        return pageCount;
    }

    /**
     * 自定义List分页工具
     * 传参:待分页的list数据、页码、页容量
     * 返回值:分页后的list数据
     */
    public static <T> List<T> getPageList(List<T> list, Integer pageNum, Integer pageSize, Integer pageCount){
   
        /**开始索引*/
        int beginIndex = 0;

        /**结束索引*/
        int endIndex = 0;

        Integer compare = pageNum.compareTo(pageCount);
        if(!compare.equals(0)){
   
            beginIndex = (pageNum - 1) * pageSize;
            endIndex = beginIndex + pageSize;
        }else{
   
            beginIndex = (pageNum - 1) * pageSize;
            endIndex = list.size();
        }
        List pageList = list.subList(beginIndex, endIndex);
        return pageList;
    }
}

五、注意点3中错误代码和正确代码的不同结果展示

错误代码

public static void listToCsvFileSaveToDirectory(List<Subscriber> list, String filePath, String fileName) {
   
...
    for (Subscriberstr : list) {
   
         csvWriter.write(str.toString());  
         csvWriter.newLine();
     }
...

错误结果展示

image.png

正确代码

public static void listToCsvFileSaveToDirectory(List<String> list, String filePath, String fileName) {
   
...
    for (String str : list) {
   
         csvWriter.write(str);  
         csvWriter.newLine();
     }
...

正确结果展示

image.png

目录
相关文章
|
1月前
|
Java API Spring
springBoot:注解&封装类&异常类&登录实现类 (八)
本文介绍了Spring Boot项目中的一些关键代码片段,包括使用`@PathVariable`绑定路径参数、创建封装类Result和异常处理类GlobalException、定义常量接口Constants、自定义异常ServiceException以及实现用户登录功能。通过这些代码,展示了如何构建RESTful API,处理请求参数,统一返回结果格式,以及全局异常处理等核心功能。
|
3月前
|
前端开发 小程序 Java
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
本文详细介绍了如何在SpringBoot项目中统一处理接口返回结果及全局异常。首先,通过封装`ResponseResult`类,实现了接口返回结果的规范化,包括状态码、状态信息、返回信息和数据等字段,提供了多种成功和失败的返回方法。其次,利用`@RestControllerAdvice`和`@ExceptionHandler`注解配置全局异常处理,捕获并友好地处理各种异常信息。
1101 0
【规范】SpringBoot接口返回结果及异常统一处理,这样封装才优雅
|
3月前
|
JSON 前端开发 Java
SpringBoot3怎么做统一结果封装?
在Spring Boot应用中,统一结果封装有助于团队协作,确保一致的API响应格式,提升代码质量和维护性。主要优点包括:简化前端集成工作,减少后端重复编码,以及增强接口的可维护性。实现上,首先定义`Result`类来封装响应状态码、消息、数据及时间戳;其次,通过`ResultCode`枚举类标准化状态信息。示例代码展示了如何构建这些类,并通过一个简单的控制器方法演示了如何使用它们返回JSON格式的响应结果。
111 2
|
3月前
|
Python
【Pandas】Pandas的DataFrame按行插入list数据或者读取一行并存为csv文件
本文提供了使用Pandas库对DataFrame进行操作的示例代码。
185 0
|
4月前
|
XML Java API
springboot基础及上传组件封装
springboot基础及上传组件封装
19 0
|
4月前
|
文字识别 Java
文本,文字识别07,SpringBoot服务开发-入参和返回值,编写接口的时候,要注意识别的文字返回的是多行,因此必须是List集合,Bean层,及实体类的搭建
文本,文字识别07,SpringBoot服务开发-入参和返回值,编写接口的时候,要注意识别的文字返回的是多行,因此必须是List集合,Bean层,及实体类的搭建
|
4月前
|
JSON Java fastjson
Spring Boot返回Json数据及数据封装
本文详细介绍了如何在Spring Boot项目中处理JSON数据的传输 Spring Boot默认使用Jackson作为JSON处理器,并通过`spring-boot-starter-web`依赖自动包含相关组件。文章还展示了如何配置Jackson处理null值,使其转换为空字符串。此外,文章比较了Jackson和FastJson的特点,并提供了FastJson的配置示例,展示了如何处理null值以适应不同应用场景。
|
5月前
|
Java
springboot封装RedisTemplate
springboot封装RedisTemplate
|
5月前
|
搜索推荐 前端开发 JavaScript
SpringBoot静态资源访问控制和封装集成方案
该文档描述了对基于SpringBoot的项目框架进行优化和整合的过程。原先采用前后端分离,后端兼做前端,但随着项目增多,升级维护变得复杂。因此,决定整合后台管理页面与后端代码,统一发布。设计上,框架包含后台管理资源,项目则配置具体业务页面,项目可通过覆盖框架资源实现个性化。关键步骤包括:自定义静态资源访问路径、解决图标与字体文件访问问题、设定自定义欢迎页面和页面图标,以及确保项目能正确访问框架静态资源。通过扫描jar包、解压和拷贝资源到项目目录,实现了框架静态资源的动态加载。此外,调整静态资源访问优先级,保证正确加载。最终实现支持jar和war包的项目结构优化。
110 4
|
5月前
|
运维 监控 Java
SpringBoot-ElasticJob封装快速上手使用(分布式定时器)
SpringBoot-ElasticJob封装快速上手使用(分布式定时器)