文件导入导出【开发实践】

文章目录

  • 一、背景和基础知识
    • [1.1 文件导入](#1.1 文件导入)
    • [1.2 文件导出](#1.2 文件导出)
    • [1.3 技术背景](#1.3 技术背景)
    • [1.4 Excel的基本知识](#1.4 Excel的基本知识)
    • [1.5 文件导入/导出流程](#1.5 文件导入/导出流程)
  • 二、使用EasyExcel完成读写Excel操作
    • [2.1 创建实体类并完成映射](#2.1 创建实体类并完成映射)
      • [2.1.1 用在字段上的注解](#2.1.1 用在字段上的注解)
        • [2.1.1.1 `@ExcelProperty`(最重要)](#2.1.1.1 @ExcelProperty(最重要))
        • [2.1.1.2 `@ColumnWidth`](#2.1.1.2 @ColumnWidth)
        • [2.1.1.3 `@ContentRowHeight`](#2.1.1.3 @ContentRowHeight)
        • [2.1.1.4 `@ContentStyle`](#2.1.1.4 @ContentStyle)
        • [2.1.1.5 `@ExcelIgnore`](#2.1.1.5 @ExcelIgnore)
      • [2.1.2 用在类上的注解](#2.1.2 用在类上的注解)
        • [2.1.2.1 `@ExcelIgnoreUnannotated`](#2.1.2.1 @ExcelIgnoreUnannotated)
        • [2.1.2.2 `@HeadStyle`](#2.1.2.2 @HeadStyle)
        • [2.1.2.3 `@HeadRowHeight`](#2.1.2.3 @HeadRowHeight)
      • [2.1.3 用在方法上的注解](#2.1.3 用在方法上的注解)
        • [2.1.3.1 `@ExcelCollection`](#2.1.3.1 @ExcelCollection)
    • [2.2 完成数据转换](#2.2 完成数据转换)
      • [2.2.1 向Sheet写数据](#2.2.1 向Sheet写数据)
        • [2.2.1.1 批量写](#2.2.1.1 批量写)
        • [2.2.1.2 遍历写(包含单次写)](#2.2.1.2 遍历写(包含单次写))
      • [2.2.2 从Sheet读数据](#2.2.2 从Sheet读数据)
  • 三、文件的上传与下载
    • [3.1 上传](#3.1 上传)
    • [3.2 同步下载](#3.2 同步下载)
  • 参考链接

一、背景和基础知识

文件导入导出功能是许多软件系统的常用功能,它允许用户将数据在不同系统、格式之间进行传输和交换。

文件导入导出功能使用的文件通常是CSV、EXCEL、XML文件。

1.1 文件导入

文件导入是指将外部文件上传到当前系统。这个过程通常涉及文件格式的识别、数据解析和持久化等步骤。

常见业务场景:批量处理数据。

1.2 文件导出

文件导出则是指将系统内部的数据转换并保存为外部文件。

常见业务场景:生成报表(用于分析和汇报),数据备份。

1.3 技术背景

Java中的文件导入导出功能最底层基于java.iojava.nio实现。针对特定类型的文件的导入导出功能,可以使用相应的框架来实现,如针对CSV文件的Apache Commons CSV和OpenCSV,针对Excel文件的Apache POI和EasyExcel等。

EasyExcel(com.alibaba.excel)是阿里开源的读写Excel文件的框架,优点是使用简单且内存占用很小(一行一行读取到内存,而不是像poi那样一次性全部读入内存)。后文将以EasyExcel为例来介绍EasyExcel文件的读写功能。

1.4 Excel的基本知识

工作簿(Workbook):一个Excel文件就是一个工作簿,它相当于一个容器,可以包含多个工作表。

工作表(Sheet):工作表是Excel工作簿中的一页,是实际存储数据的地方。每个工作表由行(ROW)和列(Column)组成,行号从1开始,列号则用字母表示,从A开始。默认情况下,一个新的Excel工作簿包含三个工作表,最多可达255个。

单元格(Cell):在Excel中,单元格是构成工作表的基本元素,是表格中行与列交叉的部分,每个单元格都有其唯一的地址,由列字母和行数字组成,比如"A1"代表的是A列与第1行交叉处的单元格。

表头(Head):工作表的最前面几行部分,用于标识各列的含义。最简单的表头就是第一行对应的部分。

1.5 文件导入/导出流程

  1. 创建实体类,完成属性和列之间的映射
  2. 完成数据转换(表格数据和列表数据之前的转换)
  3. 从request读取文件/向response写入文件(文件上传与下载)

二、使用EasyExcel完成读写Excel操作

2.1 创建实体类并完成映射

2.1.1 用在字段上的注解

2.1.1.1 @ExcelProperty(最重要)

用于指定某属性对应Excel表格中的列,主要属性如下:

  • value:根据列名/表头名来映射属性(和value二选一)。
  • index:根据(从0开始的)索引来映射属性(和index二选一)。
  • converter:指定一个实现了Converter接口的类来完成类型转换。
  • format:用来设置日期或其他类型的数据的格式。
2.1.1.2 @ColumnWidth

用于设置列的宽度,单位是字符长度,只有一个属性value,值最大为255。

2.1.1.3 @ContentRowHeight

用在字段上是用于设置行的高度,也可以用在类上,从而应用于所有字段。

2.1.1.4 @ContentStyle

用于设置单元格的格式,关键属性如下:

  • dataFormat:用来设置日期或其他类型的数据的格式。
  • hidden:用于控制单元格是否隐藏(用于隐藏一些不需要直接展示的细节)。
  • locked:控制单元格是否锁定,锁定的单元格内容不能被修改。
  • quotePrefix:当设置为true时,会在单元格内容前增加单引号,这通常用于指示Excel将数字或公式作为文本处理,避免自动格式化带来的误解。
  • horizontalAlignment:设置单元格内容的水平对齐方式,可以通过指定HorizontalAlignmentEnum枚举值来实现。
  • verticalAlignment:设置单元格内容的垂直对齐方式,可以通过指定VerticalAlignmentEnum枚举值来实现。
  • wrapped:布尔类型,决定单元格中的文本是否自动换行。如果设置为true,长文本将会在单元格内换行显示,确保内容完整可见,而不是被截断。
2.1.1.5 @ExcelIgnore

指示EasyExcel在读写时忽略该字段。

2.1.2 用在类上的注解

2.1.2.1 @ExcelIgnoreUnannotated

指示EasyExcel仅处理被@ExcelProperty等注解标记的字段,忽略未标注的字段。

2.1.2.2 @HeadStyle

用于设置Excel表头的样式,如背景色、字体样式等(用到时自己查具体怎么用)。

2.1.2.3 @HeadRowHeight

设置表头行的高度,使表头更加突出或适应复杂的表头设计。

2.1.3 用在方法上的注解

2.1.3.1 @ExcelCollection

在集合属性的getter方法上使用,用于处理集合类型的属性(用到时自己查具体怎么用)。

在导出数据到Excel时,可以将一个对象的集合属性展开,使得集合中的每个元素都能在Excel中占据一行或多行,从而形成一个二维表格区域。

从Excel读取数据时,可以识别出指定的连续区域,然后将这些数据重新组装成集合,赋值给实体类的集合属性。

2.2 完成数据转换

对于临时的读写需求,也可以不用实体类,而是使用JSON对象或Map对象,这里就不介绍了。

2.2.1 向Sheet写数据

2.2.1.1 批量写
java 复制代码
	// 为了简洁,本文的演示代码都省略了try-catch,并不规范

	// 设置排除的属性 也可以在数据模型的字段上加@ExcelIgnore注解排除
    Set<String> excludeFields = new HashSet<>();
    excludeFields.add("col1");
    excludeFields.add("col2");
    // 写Excel
    EasyExcel.write(filename, Entity.class)
            .excludeColumnFiledNames(excludeFields)
            .sheet(SheetName)
            .doWrite(entityList);
2.2.1.2 遍历写(包含单次写)

这样的好处是可以根据遍历到的元素信息决定写不写,如何写(如换sheet)。

java 复制代码
	// 1. 创建ExcelWriter对象
	ExcelWriter excelWriter = EasyExcel.write(fileName, Entity.class).build();
	// 2. 创建sheet对象
	WriteSheet writeSheet = EasyExcel.writerSheet(sheetName).build();
	// 3. 遍历数据
	for (Entity entity : entityList) {
		// 4. 将entity写入指定Excel的指定Sheet的末尾
		excelWriter.write(entity, writeSheet);
	}
	// 5. 关闭流
	excelWriter.finish()

2.2.2 从Sheet读数据

java 复制代码
	// 1. 创建ExcelReader对象
		// analysisEventListener是可选的,每读一行数据,都会使用该监听器处理一次
	ExcelReader excelReader = EasyExcel.read(fileName, Entity.class, analysisEventListener).build();
	// 2. 创建Sheet对象(按序号获取指定Sheet)
	ReadSheet sheet = EasyExcel.readSheet(0).build();
	// 3. 读取Sheet到Entity(excelReader可以用readAll读取所有sheet)
	List<Entity> entityList = excelReader.read(sheet);
	// 4. 关闭流
	excelReader.finish();

三、文件的上传与下载

3.1 上传

通过请求输入流完成文件的同步上传。

在处理器方法的参数里用MultipartFile file接收文件,然后使用EasyExcel.read来获取file对应的ExcelReader对象。后续使用ExcelReader获取Sheet对象读取即可。

java 复制代码
    @PostMapping("/upload")
    @ResponseBody
    public String upload(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), Product.class, new MyListener(productService));
        ...
        return "success";
    }

3.2 同步下载

通过请求输出流完成文件的同步下载。

java 复制代码
	response.setContentType("application/vnd.ms-excel");
    response.setCharacterEncoding("utf-8");
    response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8"));
    ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream()).build();

	// 之后使用ExcelWriter完成写Excel操作即可
	...

参考链接

EasyExce官网
EasyExcel实现Excel文件导入导出

相关推荐
星河梦瑾11 分钟前
SpringBoot相关漏洞学习资料
java·经验分享·spring boot·安全
黄名富14 分钟前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua
love静思冥想16 分钟前
JMeter 使用详解
java·jmeter
言、雲18 分钟前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
TT哇25 分钟前
【数据结构练习题】链表与LinkedList
java·数据结构·链表
Yvemil71 小时前
《开启微服务之旅:Spring Boot 从入门到实践》(三)
java
Anna。。1 小时前
Java入门2-idea 第五章:IO流(java.io包中)
java·开发语言·intellij-idea
.生产的驴1 小时前
SpringBoot 对接第三方登录 手机号登录 手机号验证 微信小程序登录 结合Redis SaToken
java·spring boot·redis·后端·缓存·微信小程序·maven
爱上语文1 小时前
宠物管理系统:Dao层
java·开发语言·宠物
王ASC2 小时前
SpringMVC的URL组成,以及URI中对/斜杠的处理,解决IllegalStateException: Ambiguous mapping
java·mvc·springboot·web