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

news/2024/4/28 20:56:50/文章来源:https://blog.csdn.net/feyehong/article/details/131619170

目录

  • 一. 需求
  • 二. `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.luyixian.cn/news_show_328271.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

初阶C语言———操作符详解(2)

hello&#xff0c;我们又见面了&#xff0c;今天我们把操作符这一章节完结&#xff0c;那让我们一起来学习吧 逻辑操作符 &&逻辑与 ||逻辑或 这里我们要区分按位与和按位或还有逻辑与和逻辑或的区分。 1&2----->0 1&&2---->1 1|2----->3 1||2---…

嵌入式_Keil (MDK - ARM) 的调试步骤

目录 1. 编译 调试 2. 复位 全速运行 3. 单步调试 4. 逐步调试 5. 跳出调试 6. 运行到光标处 7. 跳转到暂停行 8. 调试窗口 首先为什么需要在 MDK 中进行程序的调试呢&#xff1f; 在 MDK 中进行程序调试的主要目的是识别和解决程序中的问题和错误。 比如说找到程序中…

【CANopen】周立功轻松入门CANopen笔记

前言 想学习些新东西了&#xff0c;原本想直接学学Ethercat&#xff0c;但是简单看了看对象字典啥的概念一头雾水的&#xff0c;决定先从CANopen开始&#xff0c;Ethercat看着头疼。Etehrcat和CANopen有挺多类似的地方。感谢ZLG的这个入门笔记&#xff0c;我似乎是看懂了些&am…

一、枚举类型——新特性(模式匹配-支配性)

switch 中 case 语句的顺序很重要。如果基类先出现&#xff0c;就会支配任何出现在后面的 case&#xff1a; Dominance.java JDK 17 sealed interface Base { }record Derived() implements Base { }public class Dominance {static String test(Base base) {return switch (ba…

视频行为识别(一)——综述

Deep Neural Networks in Video Human Action Recognition: A Review 本次分享的文章是2023年收录在计算机视觉领域的顶刊“CVPR”&#xff08;级别&#xff1a;视觉类TOP&#xff09;期刊上。该期刊详细信息可关注公众号 AI八倍镜 点击菜单项查询。 论文地址&#xff1a;http…

代码随想录二刷day46 | 动态规划之139.单词拆分

day46 139.单词拆分1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp[i] 139.单词拆分 题目链接 解题思路&#xff1a;单词就是物品&#xff0c;字符串s就是背包&#xff0c;单词能否组成字符串s&#xff0c;就是问物品能不能把背包装满…

第三章 SSD存储介质:闪存 3.4

3.4 闪存数据完整性 可采用以下数据完整性的技术确保用户数据不丢失&#xff1a; &#xff08;1&#xff09;ECC纠错&#xff1b; &#xff08;2&#xff09;RAID数据恢复&#xff1b; &#xff08;3&#xff09;重读&#xff08;Read Retry&#xff09;&#xff1b; &#xff…

vue 进阶---动态组件 插槽 自定义指令

目录 动态组件 如何实现动态组件渲染 使用 keep-alive 保持状态 keep-alive 对应的生命周期函数 keep-alive 的 include 属性和exclude属性 插槽 插槽的基础用法 具名插槽 作用域插槽 自定义指令 自定义指令的分类 私有自定义指令 全局自定义指令 了解 eslint 插件…

免费开源 | 基于SpringBoot的博客系统

介绍 基于springboot后端架构&#xff0c;websocket实现私信&#xff0c;前端采用thymeleafbootstraplayuiRedis 注册使用邮箱验证注册&#xff0c;且验证码存在redis中&#xff0c;所以需要有redis环境 软件架构 springbootwebsocketthymeleafbootstraplayuiRedismysql 8.…

Vue 数据双向绑定

双向数据绑定 : 通过前面学习知道 Vue 是数据驱动的&#xff0c;数据驱动有一个精髓之处是数据双向绑定&#xff0c; 即当数据发生变化的时候&#xff0c;视图也就发生变化&#xff0c;当视图发生变化的时候&#xff0c;数据也会跟着同步变化。&#xff08;就是mvvm数据发生变化…

C#,中国福利彩票《刮刮乐》的数学算法(01)——幸运123

彩票名称&#xff1a;幸运123面值&#xff1a;20元/张最高奖&#xff1a;100万&#xff08;人民币&#xff09;全套款式&#xff1a;2款玩法介绍&#xff1a; 一份好运&#xff0c;二倍快乐&#xff0c;三重惊喜。福彩刮刮乐新游戏“幸运123”&#xff0c;红色的票面上点缀着礼…

spring 详解二 IOC(Bean xml配置及DI)

配置列表 Xml配置 功能描述 <bean id"" class""></bean> Bean的id&#xff0c;配置id会转为Bean名称和不配就是全限定类名 <bean name"" ></bean> Bean的别名配置&#xff0c;存储在Factory的aliasMap中通过别名也…

Qt自定义控件之动画文本

文章目录 前言一、动画文本的效果二、具体实现定义动画对象设置动画时长的实现设置text函数实现绘制代码设置字体函数 三、高级部分操作代码总结 前言 在 Qt 中&#xff0c;自定义控件可以让我们实现丰富的用户界面效果和交互体验。其中&#xff0c;动画文本是一种常见的效果&…

使用 tail -f 实时观测服务器日志输出

在开发阶段, 有 console 端的输出, 总是可以方便实时地看到应用的日志. 可一旦应用部署到服务器上之后呢, 日志被输出到文件中, 在某些情景下需要不停地查看日志文件的输出以定位某些问题, 此时是否还能像开发那样实时查看日志呢? 答案是可以的! 这个命令就是 tail -f . tail…

Git使用详细教程

1. cmd面板的常用命令 clear&#xff1a;清屏cd 文件夹名称----进入文件夹cd … 进入上一级目录(两个点)dir 查看当前目录下的文件和文件夹(全拼:directory)Is 查看当前目录下的文件和文件夹touch 文件名----创建文件echo 内容 > 创建文件名----创建文件并写入内容rm 文件名…

Redis知识补充(1)

1)Redis本身就是在内存中进行存储数据的&#xff0c;那么为什么不直接定义一个变量来针对数据直接进行存储呢&#xff1f;因为Redis主要是应用于分布式系统&#xff0c;才能发挥它的最大威力&#xff0c;如果只是一个单机程序&#xff0c;通过变量存储数据的方式&#xff0c;是…

Kotlin~Composite组合模式

概念 能够帮助实现树状结构的模式。 主要特点 递归组合树状结构统一处理所有对象 角色介绍 Component: 组合接口Leaf: 叶子节点&#xff0c;无子节点Composite&#xff1a;枝节点&#xff0c;用来存储子部件 UML 代码实现 interface Organ {fun personCount():Int } cla…

[VUE学习】从头搭建权限管理系统前端-初始化

1.安装Node 2.安装Vue Cli vue的一个脚手架 npm install -g vue/cli 3.vue ui搭建vue项目 cmd 运行 vue ui 然后创建新项目 选择npm 选择配置 Babel 是编译的 Router 是路由 vuex 是状态保存的 Linter/fomatter 代码检测和格式化 创建完成 这个时候 代码在我们本地…

解决IDEA/WebStorm的Ctrl+Shift+F冲突失效

IDEA 的 CtrlShiftF 是全文或全项目搜索搜索快捷键&#xff0c;非常好用。 当这个快捷键偶而会失效时&#xff0c;基本可以确定是快捷键冲突了。 检查所有运行的软件的快捷键&#xff0c;若有设置为CtrlShiftF的则改掉。特别是输入法会占用较多的快捷键。 例如我这里的搜过输…

Skywalking高级使用

Skywalking高级使用 RPC调用监控Mysql调用监控Skywalking常用插件获取追踪ID过滤指定的端点告警功能Skywalking原理Open Tracing介绍 RPC调用监控 Skywalking(6.5.0)支持的RPC框架有以下几种&#xff1a; (1) Dubbo 2.5.4 -> 2.6.0 (2) Dubbox 2.8.4 (3) Apache Dubbo 2.7.…