poi讀取Excel文件,讀取csv文件,我的開源工具類

本文首發於我的個人網站:
http://riun.xyz


前言

程序中經常使用代碼讀取Excel或Csv文件,每次都要寫繁瑣的讀取代碼,於是我就寫了一個工具類去讀取文件,並將結果儲存爲常用的格式。方便我們快速的拿到結果進行入庫或其他處理。不再將精力浪費在處理文件上。

下面我將全面介紹此工具類。

預備知識

csv文件,一種文本文件格式,以行爲單位儲存數據。每行中的數據以逗號分隔,可以以excel方式打開。

poi,一種java讀取excel文件的工具。可以對行,或特定的單元格進行讀取。

使用

案例:讀取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。

package riun.xyz.Demo4;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

/**
 * @author: HanXu
 * on 2019/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中的屬性名字。必選的只有這兩個參數,讓我們試試:

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() + "條記錄");
    }
}

輸出內容爲:

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對象,接下來你就可以開心的做其他處理啦。

參數含義

上述代碼只使用一行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個參數,其中兩個是必選的,其他是非必選的。就是說還能使用其他方式讀取,例如:

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個參數全部手動傳入。

案例:讀取Csv文件

1、準備一個Csv文件,你可以點這兒下載一個【文件testcsv.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。

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對象,讓我們試試:

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());
    }

}

輸出內容爲:

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

已經得到對象集合數據了,接下來可以進行入庫或者其他處理了。

參數含義

上述代碼仍然是使用一行List<Emp> result = HPoiUtils.exeCsv(file, listField, Emp.class);即可讀取到文件中的數據並轉化爲對象集合返回。其中參數和上面讀取Excel文件時差不多,只少了一個sheet參數。

下面是參數解釋:

  • file:csv文件。必選
  • listField:文件中每列代表的屬性名字集合。必選
  • class:文件中每行對應的對象。可選,不傳入時程序在運行期間會生成一個動態類。
  • hasHeader:是否有表頭信息。可選,默認爲true,即有表頭信息。

性能測試

上面讀取到的數據都太小了,我們換一個稍微大點的文件試試:

Excel:125條數據,712ms
在這裏插入圖片描述

Csv:1719條數據,499ms
在這裏插入圖片描述

依賴

<!--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>

源碼解釋

本工具處理過程大致分爲如下幾步:

1、參數檢查

2、獲取String結果

3、將String結果對象化

其中第2步,獲取String結果時,根據不同文件,按照給定的sheet進行讀取,讀取時不會判斷是否有表頭,將全部數據讀取,根據傳入的list.size可以進行邏輯分組。

第3步,String對象化時使用了反射,如果傳入有類,就按照類動態生成對象,並根據list中儲存的屬性名字動態執行setter方法,將讀取到的String類型的數據設置進去。

如果沒有傳入類,就動態生成一個類,然後再執行上述。

關於

此工具是我之前HPoiUtils的前身,當時指向讀取Excel文件,後來寫着寫着就加上了讀取Csv文件,更多詳細及歷史版本參見github:https://github.com/hanhanhanxu/HPoiUtil

這個工具類我還會持續更新下去,歡迎給我提各種意見或建議(●’◡’●)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章