Java csv文件上传下载中的相关转换

news/2024/11/23 3:58:00/

目录

  • 一. 需求
  • 二. `List<Entity>`转`List<List<String>>`
    • 2.1 实体类
    • 2.2 转换
  • 三. 上传csv文件转`List<Map>`
    • 3.1 csv文件
    • 3.2 前台
    • 3.3 实体类
    • 3.4 转换
    • 3.5 效果


一. 需求

🤔项目中遇到了两个需求

1.查询数据库,得到List<Entity>这种数据类型,然后需要将List<Entity>转换为List<List<String>>之后,调用共通方法下载CSV数据。
2.前台上传csv文件到后台,后台需要将csv文件处理为List<Map>这种数据类型,然后遍历List插入数据库。


二. List<Entity>List<List<String>>

2.1 实体类

  • 在类的内部定义了一个@excludeCSV注解,用于标识指定的属性不进行转换
import lombok.Builder;
import lombok.Data;import java.lang.annotation.*;@Data
@Builder
public class Category {@Retention(RetentionPolicy.RUNTIME)@Target({ElementType.FIELD})public @interface excludeCSV {}private String id;@excludeCSVprivate String password;private String parentValid;private String parentId;private String name;private String updateTime;
}

2.2 转换

  • 要点就是反射,因为实体类的属性都是private,所以需要使用 .setAccessible(true) 使其强制可访问。
  • 因为不确定List中的类型是什么,因此使用 List<?>
  • 部分属性不需要转换,使用自定义注解@excludeCSV来标识。
import org.springframework.boot.CommandLineRunner;import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import java.lang.reflect.Field;
import java.util.*;@Controller
@RequestMapping("/test33")
public class Test33Controller implements CommandLineRunner {@Overridepublic void run(String... args) throws Exception {// 模拟从数据库查询到的List<Entity>数据List<Category> categoryList = List.of(Category.builder().id("1").name("张三").parentId("11").updateTime("2023").build(),Category.builder().id("2").name("李四").parentId("22").updateTime("2024").build(),Category.builder().id("3").name("王五").parentId("33").updateTime("2025").build());// 进行转换List<List<String>> csvDataList = this.handleData(categoryList);System.out.println(csvDataList);/*[[1, , 11, 张三, 2023], [2, , 22, 李四, 2024], [3, , 33, 王五, 2025]]*/}public List<List<String>> handleData(List<?> dataList) throws IllegalAccessException {List<List<String>> strList = new ArrayList<>();List<String> valueList;Field[] fields;for (Object data : dataList) {valueList = new ArrayList<>();// 获取所有修饰符的属性fields = data.getClass().getDeclaredFields();for (Field field : fields) {// 如果包含指定的注解,则该csv项目不处理if (field.isAnnotationPresent(Category.excludeCSV.class)) {continue;}// 使该属性强制可访问field.setAccessible(true);// 获取属性值valueList.add(Optional.ofNullable(field.get(data)).orElse("").toString());}strList.add(valueList);}return strList;}
}

三. 上传csv文件转List<Map>

3.1 csv文件

"ID","姓名","年龄","地址"
"1","张三",18,"山东省"
"2","李四",19,"山西省"

3.2 前台

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><input type="file" id="csv" accept=".csv" /><button id="btn">上传文件</button>
</body>
<script type="text/javascript" th:src="@{/js/public/jquery-3.6.0.min.js}"></script>
<script>$(function() {bindEvent();});function bindEvent() {$("#btn").click(() => {const formData = new FormData();formData.append("multipartFile", $("#csv").get(0).files[0]);$.ajax({url: `/test33/fileUpload`,type: 'POST',processData: false,contentType: false,data: formData,success: function (data, status, xhr) {console.log(data);}});});}
</script>
</html>

3.3 实体类

import lombok.Data;
import org.springframework.web.multipart.MultipartFile;@Data
public class Test33Form {// 用来接收前台传入的csv文件private MultipartFile multipartFile;
}

3.4 转换

  • 因为上传的不是json数据,因此使用Form接收的时候不需要加@RequestBody
  • 后台接收到的文件类型为MultipartFile,需要将其转换为File后读取其中的内容。
  • 可以使用File.createTempFile()创建临时文件,使用完之后需要删除,否则占用磁盘空间。
  • 可以使用Files.readAllLines()读取全部的文本文件数据。
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.*;@Controller
@RequestMapping("/test33")
public class Test33Controller {private static final String CHARSET = "UTF-8";// CSV列的字段名映射private Map<Integer, String> csvColumnMap = new HashMap<>(){{put(0, "id");put(1, "name");put(2, "age");put(3, "address");}};@PostMapping("/fileUpload")public ResponseEntity<Void> fileUpload(Test33Form form) throws IOException {// 获取前台上传的csvMultipartFile multipartFile = form.getMultipartFile();// 将csv文件临时存储到本地String originalFilename = multipartFile.getOriginalFilename();// 获取文件名以及文件名的后缀String fileName = StringUtils.stripFilenameExtension(originalFilename);String filenameExtension = StringUtils.getFilenameExtension(originalFilename);// 创建临时文件File tempFile = File.createTempFile(fileName, filenameExtension);multipartFile.transferTo(tempFile);// 指定通过 UTF-8 编码读取CSV中的数据; 如果读取的是日语文件,通常格式为 Shift_JISList<String> csvList = Files.readAllLines(tempFile.toPath(), Charset.forName(CHARSET));// 删除csv文件中的第一行的标题csvList.remove(0);// 删除临时文件Files.delete(tempFile.toPath());List<Map<String, Object>> csvMapList = new ArrayList<>();for (String csvRow : csvList) {Map<String, Object> csvMap = new HashMap<>();List<String> csvItemList = Arrays.asList(csvRow.split(","));for (int i = 0; i < csvItemList.size(); i++) {csvMap.put(csvColumnMap.get(i), csvItemList.get(i));}csvMapList.add(csvMap);}System.out.println(csvMapList);// 响应给前台return ResponseEntity.noContent().build();}
}

3.5 效果

在这里插入图片描述


http://www.ppmy.cn/news/789819.html

相关文章

[物理层]传输方式

传输方式 串行传输与并行传输 穿行传输是指数据是一个比特一个比特依次发送的&#xff0c;在发送端与接收端只用一条数据线路 并行传输是指一次发n个比特&#xff0c;在发送端与接收端需要n条数据线路 在网络中计算机通信通常采用串行传输&#xff1b;而在计算机内部&#x…

从零开始的PICO教程(2)--实时预览应用场景

从零开始的PICO教程&#xff08;2&#xff09;–实时预览应用场景 基于串流能力&#xff0c;你可以通过 PDC 工具在头戴上实时预览应用内场景。​ 文章目录 从零开始的PICO教程&#xff08;2&#xff09;--实时预览应用场景一、提示信息​二、准备工作​三、操作步骤​四、故…

市面上最火爆的气传导耳机有哪些,试试这几款气传导耳机

作为一个标准的当代社恐人&#xff0c;我每次出门的时候都会戴上耳机&#xff0c;听着自己喜欢的音乐&#xff0c;那种恐惧感就会逐渐减少。而且&#xff0c;戴上耳机之后更方便接打电话&#xff0c;一款优质耳机简直就是社恐人士的福音有木有&#xff01;现在流行气传导耳机&a…

大联大品佳集团推出基于Audiowise产品的蓝牙5.1助听(Hearing Device)耳机方案

2022年3月3日&#xff0c;致力于亚太地区市场的领先半导体元器件分销商—大联大控股宣布&#xff0c;其旗下品佳推出基于原睿科技&#xff08;Audiowise&#xff09;PAU1825芯片的蓝牙5.1助听&#xff08;Hearing Device&#xff09;耳机方案。 图示1-大联大品佳基于Audiowise产…

简单介绍红白机的发声系统以及其它音源 MMC

红白机的音源 Yamato Ryou 2013-08-23 14:52:26 本文将简单介绍红白机的发声系统以及其它音源 MMC, 红白机下称 FC, 其中的伪声音处理器称作 APU. 我才不告诉你称作 2A03 其实也没错. APU 有 5 个通道: 2 个方波 / 矩形波通道: 首先说一下方波和矩形波的区别, 但是在此之前要…

索尼推出全新无线颈挂式扬声器;新思科技与三星合作推广3纳米GAA技术;中国汽车系统为阿尔法罗密欧开发新型转向系统 | 全球TMT...

大公司动向 索尼电子(Sony Electronics)宣布推出全新无线颈挂式扬声器SRS-NB10&#xff0c;使人们可以在舒适的环境下接听会议电话、听音乐和自由走动。NB10针对声音进行了优化&#xff0c;凭借“精确语音拾音技术”、两枚波束成形麦克风以及先进的语音信号处理技术&#xff0c…

ios15.6RC-15.7.1系统降级iOS14,适用于checkm8机型

1、进入DFU模式 把你的手机进入到 DFU mode.如果不会&#xff0c;自行百度。 安装Python 3.8 如果没有安装过python3 &#xff0c;在终端输入一下命令 brew install python3 安装完Python3之后再执行以下命令 python3 -m pip install --user --force-reinstall https://github…

AWS助力海信集团智慧家居全球化运营

在8月31日至9月5日举办的2022年中国国际服务贸易交易会中&#xff0c;AWS助力海信集团智慧家居全球化运营获选“全球服务实践案例”&#xff0c;展现了AWS赋能企业创新的卓越实力。 数字经济时代&#xff0c;各行各业都在积极尝试出海与智能化转型&#xff0c;以占领更多受众及…