基於 java 註解的 csv 檔案讀寫框架

葉止水發表於2019-06-03

csv

基於 java 註解生成加簽驗籤 csv。

開源地址: github

創作原由

以前覺得 csv 檔案的多寫非常簡單,就懶得封裝。

最近一個月寫了兩次 csv 檔案相關的東西,發現要處理的細節還是有的,還浪費比較多的時間。

比如:

  1. UTF-8 中文編碼使用 excel 開啟亂碼,因為缺少 BOM 頭。

  2. 不同型別欄位轉化為字串,順序的指定,head 頭的指定,如果手寫都會很繁瑣。

  3. 讀取的時候最後 , 後無元素,split 會缺失等。

為了解決上述問題,此框架應運而生。

特性

  • Fluent 流式寫法

  • 基於 java 註解

  • 欄位型別轉換的靈活支援,內建 8 大基本型別以及 String 型別轉換

快速開始

環境

jdk7+

maven 3.x

maven 引入

<dependency>
    <groupId>com.github.houbb</groupId>
    <artifactId>csv</artifactId>
    <version>0.0.2</version>
</dependency>
複製程式碼

示例程式碼

  • User.java

演示基本型別的轉換

public class User {

    private String name;

    private int age;

    private float score;

    private double money;

    private boolean sex;

    private short level;

    private long id;

    private char status;

    private byte coin;

    //Getter & Setter & toString()
}
複製程式碼
  • 物件列表構建
    /**
     * 構建通用測試列表
     * @return 列表
     */
    private List<User> buildCommonList() {
        User user = new User();
        short s = 4;
        byte b = 1;
        user.age(10)
        .name("你好")
        .id(1L)
        .score(60)
        .coin(b)
        .level(s)
        .money(200)
        .sex(true)
        .status('Y');
        return Arrays.asList(user);
    }
複製程式碼

寫入

  • 測試程式碼
public void commonTest() {
    final String path = "src\\test\\resources\\common.csv";
    CsvWriteBs.newInstance(path)
            .write(buildCommonList());
}
複製程式碼
  • 檔案生成
name,age,score,money,sex,level,id,status,coin
你好,10,60.0,200.0,true,4,1,Y,1
複製程式碼

讀取

public void commonTest() {
    final String path = "src\\test\\resources\\common.csv";
    List<User> userList = CsvReadBs.newInstance(path)
            .read(User.class);
    System.out.println(userList);
}
複製程式碼
  • 日誌資訊
[User{name='你好', age=10, score=60.0, money=200.0, sex=true, level=4, id=1, status=Y, coin=1}]
複製程式碼

CSV 引導類

為了使用者使用的便利性,和後期擴充的靈活性。

引導類

CSV 有兩個引導類:

名稱 作用
CsvWriteBs csv 檔案寫入引導類
CsvReadBs csv 檔案讀取引導類

CsvWriteBs

方法 預設值 說明
newInstance(final String path) 必填 建立例項,並且指定待寫入檔案路徑。
writeBom(boolean writeBom) true 是否寫入 UTF8 BOM 頭,建議第一次寫入指定,避免中文亂碼
charset(String charset) UTF-8 指定檔案編碼
sort(ISort sort) NoSort 預設不進行欄位排序
write(List list) 待寫入的檔案列表

CsvReadBs

方法 預設值 說明
newInstance(final String path) 必填 建立例項,並且指定待讀取檔案路徑。
charset(String charset) UTF-8 指定檔案編碼
sort(ISort sort) NoSort 預設不進行欄位排序
startIndex(int startIndex) 1 檔案的第二行,預設第一行是 head
endIndex(int endIndex) 檔案的最後一行

Csv 註解

註解屬性說明

用於待處理物件的欄位上。

    /**
     * 欄位顯示名稱
     * 1. 預設使用 field.name
     * @return 顯示名稱
     */
    String label() default "";

    /**
     * 讀取是否需要
     * @return 是
     */
    boolean readRequire() default true;

    /**
     * 寫入是否需要
     * @return 是
     */
    boolean writeRequire() default true;

    /**
     * 讀取轉換
     * @return 處理實現類
     */
    Class<? extends IReadConverter> readConverter() default CommonReadConverter.class;

    /**
     * 寫入轉換
     * @return 處理實現類
     */
    Class<? extends IWriteConverter> writeConverter() default StringWriteConverter.class;
複製程式碼

屬性概覽表

屬性 預設值 說明
label 欄位名稱 用於 csv 頭生成
readRequire true 是否需要從 csv 檔案讀取
writeRequire true 當前欄位是否需要寫入 csv 檔案
readConverter CommonReadConverter 將 csv 中的字串轉化為當前欄位型別,支援 8 大基本型別+String
writeConverter StringWriteConverter 直接呼叫當前欄位值 toString() 方法,null 直接為空字串

其中 readConverter/writeConverter 支援使用者自定義

註解使用程式碼示例

物件定義

public class UserAnnotation {

    @Csv(label = "名稱")
    private String name;

    @Csv(label = "密碼", readRequire = false, writeRequire = false)
    private String password;

    @Csv(label = "生日", readConverter = ReadDateConvert.class, writeConverter = WriteDateConvert.class)
    private Date birthday;

    //Getter & Setter & toString()
}
複製程式碼

ReadDateConvert/WriteDateConvert

使我們自定義的針對 Date 的轉換實現。

  • Write
public class WriteDateConvert implements IWriteConverter<Date> {

    @Override
    public String convert(Date value) {
        DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        return dateFormat.format(value);
    }

}
複製程式碼
  • ReadDateConvert
public class ReadDateConvert implements IReadConverter<Date> {

    @Override
    public Date convert(String value, Class fieldType) {
        try {
            DateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            return dateFormat.parse(value);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }

}
複製程式碼

寫入檔案

public void annotationTest() {
    final String path = "src\\test\\resources\\annotation.csv";
    CsvWriteBs.newInstance(path)
            .write(buildAnnotationList());
}
複製程式碼

其中列表構建:

/**
 * 構建基於註解的測試列表
 * @return 列表
 */
private List<UserAnnotation> buildAnnotationList() {
    UserAnnotation user = new UserAnnotation();
    user.name("你好")
            .password("123")
            .birthday(new Date());
    return Arrays.asList(user);
}
複製程式碼
  • 生成檔案內容
名稱,生日
你好,20190603
複製程式碼

讀取檔案測試

public void annotationTest() {
     final String path = "src\\test\\resources\\annotation.csv";
     List<UserAnnotation> userList = CsvReadBs.newInstance(path)
             .read(UserAnnotation.class);
     System.out.println(userList);
}
複製程式碼
  • 日誌資訊
[UserAnnotation{name='你好', password='null', birthday=Mon Jun 03 00:00:00 CST 2019}]
複製程式碼

相關文章