我的开源工具类 2020-06-18 22:59 ### 1、前言 程序中经常使用代码读取Excel或Csv文件,每次都要写繁琐的读取代码,于是我就写了一个工具类去读取文件,并将结果储存为常用的格式。方便我们快速的拿到结果进行入库或其他处理。不再将精力浪费在处理文件上。 下面我将全面介绍此工具类。 ### 2、预备知识 csv文件,一种文本文件格式,以行为单位储存数据。每行中的数据以逗号分隔,可以以excel方式打开。 poi,一种java读取excel文件的工具。可以对行,或特定的单元格进行读取。 ### 3、使用 #### 3.1、案例:读取Excel文件 1、准备一个Excel文件,你可以点这儿下载一个( https://github.com/hanhanhanxu/HPoiUtil/blob/master/pleasedownloadme/testexcel.xlsx )【鼠标放在链接上,选择‘链接另存为’】,或者准备你自己的。我的文件中的数据是这样的: | 部门名称 | 班级名称 | 学号 | 姓名 | 收费年度 | 总账欠费金额 | 欠费金额 | | -------- | ---------------------------- | ---------- | ------ | -------- | ------------ | --------- | | 1 | 16软件工程(JAVA技术应用方向) | 45asdf4w23 | 路飞 | 2019年度 | 13,800.00 | 13,800.00 | | 2 | 16软件工程(JAVA技术应用方向) | 34534sdf34 | 乌索普 | 2019年度 | 5,800.00 | 5,800.00 | | 3 | 软件设计 | 346e5tertw | 索隆 | 2019年度 | 13,800.00 | 13,800.00 | | 4 | 软件设计 | 3456eyerge | 山治 | 2019年度 | 13,800.00 | 13,800.00 | | 5 | 软件设计 | 345e4twset | 娜美 | 2019年度 | 13,800.00 | 13,800.00 | | 6 | 软件设计 | 345634etr2 | 罗宾 | 2019年度 | 13,800.00 | 13,800.00 | 2、准备pojo对象。此对象的含义是,你最终将读取到的Excel文件中的数据转化为什么对象。比如我excel文件中的数据其实是学生 Student 对象,那么就新建一个 Student.java。 ```java package riun.xyz.Demo4; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.util.Date; /** * @author: HanXu * on 2020/06/18 * Class description: */ @Data @AllArgsConstructor @NoArgsConstructor public class Student { private Integer id; private Integer depId; private String className; private String sno; private String name; private String year; private Float allAmountArrears; private Float amountArrears; private Date createTime; } ``` Excel文件中每列都有它的含义,对应着pojo类的属性。下面是属性对照关系。需要注意的是,允许存在pojo类中有的属性,而Excel没有那一列数据。例如本例中的id,createTime。  3、获取HPoiUtils.java 的源码,你可以点这儿下载( https://github.com/hanhanhanxu/HPoiUtil/blob/master/pleasedownloadme/HPoiUtils.java )【鼠标放在链接上,选择‘链接另存为’】。 4、编写测试案例。 想要读取Excel文件中的数据,你需要在代码里准备一个文件file;一个集合list,此集合中存放的是Excel文件中每列代表含义,即这列映射到pojo中的属性名字。必选的只有这两个参数,让我们试试: ```java package riun.xyz.nice.Demo1.all; import org.apache.commons.beanutils.BeanUtils; import riun.xyz.Demo4.HPoiUtils; import riun.xyz.Demo4.Student; import java.io.File; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.List; /** * @author: HanXu * on 2020/6/18 * Class description: 读取excel文件的测试 */ public class Test { //准备文件file static final File file = new File("D:\\05HxUtils\\1\\testexcel.xlsx"); //准备属性集合list private static List<String> genListField() { List<String> listField = new ArrayList(12);//建议使用ArrayList,get(i)操作更快 listField.add("depId"); listField.add("className"); listField.add("sno"); listField.add("name"); listField.add("year"); listField.add("allAmountArrears"); listField.add("amountArrears"); return listField; } public static void main(String[] args) { test2(); } public static void test2() { List<String> listField = genListField(); //执行 List result = HPoiUtils.exe(file, listField); for (Object o : result) { //类格式输出 Student student = new Student(); try { BeanUtils.copyProperties(student, o); } catch (IllegalAccessException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } System.out.println(student); //json格式输出 /*System.out.println( nice GsonBuilder().setPrettyPrinting().create().toJson(o)); System.out.println();*/ } System.out.println("共" + result.size() + "条记录"); } } ``` 输出内容为: ```cmake Student(id=null, depId=1, className=16软件工程(JAVA技术应用方向), sno=45asdf4w23, name=高新杰, year=2019年度, allAmountArrears=13800.0, amountArrears=13800.0, createTime=null) Student(id=null, depId=2, className=16软件工程(JAVA技术应用方向), sno=34534sdf34, name=刘德华, year=2019年度, allAmountArrears=5800.0, amountArrears=5800.0, createTime=null) Student(id=null, depId=3, className=软件设计, sno=346e5tertw, name=许文瑞, year=2019年度, allAmountArrears=13800.0, amountArrears=13800.0, createTime=null) Student(id=null, depId=4, className=软件设计, sno=3456eyerge, name=张奕东, year=2019年度, allAmountArrears=13800.0, amountArrears=13800.0, createTime=null) Student(id=null, depId=5, className=软件设计, sno=345e4twset, name=蒋海靖, year=2019年度, allAmountArrears=13800.0, amountArrears=13800.0, createTime=null) Student(id=null, depId=6, className=软件设计, sno=345634etr2, name=徐凯, year=2019年度, allAmountArrears=13800.0, amountArrears=13800.0, createTime=null) 共6条记录 ``` 已经成功读取 Excel文件并将结果转化为Student对象,接下来你就可以开心的做其他处理啦。 #### 3.2、参数含义 上述代码只使用一行HPoiUtils.exe就能读取到文件,拿到结果对象集合了。下面将介绍此方法的几个参数: - file:一个Excel文件。**必选** - sheetIndex或sheetName:sheetIndex代表sheet索引值,即第几个sheet,从0开始;sheetName代表sheet名字。**可选**,默认为0,即读取第一个sheet的内容 - list:属性集合,集合中的元素代表Excel中对应列的意义,一一对应。**必选** - class:表示想要转化成的对象,即将Excel表中的行记录转化为什么对象。**可选**,不传入时会根据传入list的内容动态生成一个类。大多数时候,建议手动传入 - hasHeader:Excel中是否有有表头,true,是,则读取时不会读取第一行数据;false,否,当你的Excel文件中没有表头,第一行就是数据时,传入false。**可选**,默认为true 共有5个参数,其中两个是必选的,其他是非必选的。就是说还能使用其他方式读取,例如: ```java List result = HPoiUtils.exe(file, listField, false); # 读取时将认为Excel文件中没有表头,会把第一行也认为是数据并读取转化为对象。 List result = HPoiUtils.exe(file, 1, listField); # 读取Excel中的第1个sheet(为0时可不传,表示读取第一个;为1表示读取第二个sheet;此处也可传入sheet名字,不区分大小写) List<Student> result = HPoiUtils.exe(file, listField, Student.class); # 读取到的数据直接就是Student,不用再转换。通常情况下,建议传入类。 ``` 你也可以选择5个参数全部手动传入。 #### 3.3、案例:读取Csv文件 1、准备一个Csv文件,你可以点这儿下载一个( https://github.com/hanhanhanxu/HPoiUtil/blob/master/pleasedownloadme/testcsv.csv )【鼠标放在链接上,选择‘链接另存为’。或者直接新建txt文件,将下面内容复制进去然后修改后缀名为csv】,或者准备你自己的。我的文件中的数据是这样的: ```csv id,name,pass,age,sary 1,qweqw,asdfa,12.32 2,45wes,dfgdf,435.309 3,asdt,asdf,345.23 ``` 2、准备pojo对象。此对象的含义是,你最终将读取到的Csv文件中的数据转化为什么对象。比如我csvl文件中的数据其实是员工 Emp 对象,那么就新建一个 Emp.java。 ```java package riun.xyz.nice.Demo1.all; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; /** * @author: Hanxu * @Date: 2020/6/18 22:21 */ @Data @AllArgsConstructor @NoArgsConstructor public class Emp { private Long id; private String name; private String pass; private Float sary; private String other; } ``` 3、获取HPoiUtils.java 的源码。 4、编写测试案例。 想要读取Csv文件中的数据,你需要在代码里准备一个文件file;一个集合list,此集合中存放的是Csv文件中每列代表含义,即这列映射到pojo中的属性名字。必选的只有这两个参数,但是我们通常都建议明确传入class对象,即Emp.class对象,让我们试试: ```java package riun.xyz.nice.Demo1.all; import riun.xyz.Demo5.RepeaterDebtTermDto; import java.io.File; import java.util.ArrayList; import java.util.List; /** * @author: HanXu * on 2020/6/16 * Class description: 读取Csv文件的测试 */ public class Test { //准备文件file static final File file = new File("D:\\05HxUtils\\1\\testcsv.csv"); //准备属性集合list private static List<String> genListField() { List<String> listField = new ArrayList(10);//建议使用ArrayList,get(i)操作更快 listField.add("id"); listField.add("name"); listField.add("pass"); listField.add("sary"); return listField; } public static void main(String[] args) { test1(); } public static void test1() { List<String> listField = genListField(); //执行 List<Emp> result = HPoiUtils.exeCsv(file, listField, Emp.class); for (Emp o : result) { System.out.println(o); //System.out.println( nice GsonBuilder().setPrettyPrinting().create().toJson(o)); } System.out.println(result.size()); } } ``` 输出内容为: ```cmake Emp(id=1, name=qweqw, pass=asdfa, sary=12.32, other=null) Emp(id=2, name=45wes, pass=dfgdf, sary=435.309, other=null) Emp(id=3, name=asdt, pass=asdf, sary=345.23, other=null) 3 ``` 已经得到对象集合数据了,接下来可以进行入库或者其他处理了。 #### 3.4、参数含义 上述代码仍然是使用一行`List<Emp> result = HPoiUtils.exeCsv(file, listField, Emp.class);`即可读取到文件中的数据并转化为对象集合返回。其中参数和上面读取Excel文件时差不多,只少了一个sheet参数。 下面是参数解释: - file:csv文件。**必选**。 - listField:文件中每列代表的属性名字集合。**必选**。 - class:文件中每行对应的对象。**可选**,不传入时程序在运行期间会生成一个动态类。 - hasHeader:是否有表头信息。**可选**,默认为true,即有表头信息。 ### 4、性能测试 上面读取到的数据都太小了,我们换一个稍微大点的文件试试: Excel:125条数据,712ms  Csv:1719条数据,499ms  ### 5、依赖 ```xml <!--poi--> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.17</version> </dependency> <!--javassist.*--> <dependency> <groupId>org.javassist</groupId> <artifactId>javassist</artifactId> <version>3.18.2-GA</version> </dependency> <!--工具类--> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.5</version> </dependency> <!--pojo类的setter getter等方法--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.12.6</version> </dependency> <!--不传入类时,类拷贝--> <dependency> <groupId>commons-beanutils</groupId> <artifactId>commons-beanutils</artifactId> <version>1.9.3</version> </dependency> <!--输出json样式--> <dependency> <groupId>com.google.code.gson</groupId> <artifactId>gson</artifactId> <version>2.8.5</version> </dependency> ``` ### 6、源码解释 本工具处理过程大致分为如下几步: 1、参数检查 2、获取String结果 3、将String结果对象化 其中第2步,获取String结果时,根据不同文件,按照给定的sheet进行读取,读取时不会判断是否有表头,将全部数据读取,根据传入的list.size可以进行逻辑分组。 第3步,String对象化时使用了反射,如果传入有类,就按照类动态生成对象,并根据list中储存的属性名字动态执行setter方法,将读取到的String类型的数据设置进去。 如果没有传入类,就动态生成一个类,然后再执行上述。 ### 7、关于 此工具是我之前HPoiUtils的前身,当时指向读取Excel文件,后来写着写着就加上了读取Csv文件,更多详细及历史版本参见github:https://github.com/hanhanhanxu/HPoiUtil > 这个工具类我还会持续更新下去,欢迎给我提各种意见或建议(●'◡'●) --END--
发表评论