Java實(shí)現(xiàn)對(duì)象轉(zhuǎn)CSV格式
介紹
csv全稱“Comma-Separated Values”,是一種逗號(hào)分隔值格式的文件,是一種用來存儲(chǔ)數(shù)據(jù)的純文本格式文件。CSV文件由任意數(shù)目的記錄組成,記錄間以某種換行符分隔;每條記錄由字段組成,字段間的分隔符是其它字符或字符串。
Java對(duì)象轉(zhuǎn)CSV,有現(xiàn)成的工具包,commons-lang3 的ReflectionToStringBuilder 就可以簡(jiǎn)單的解決的對(duì)象轉(zhuǎn)CSV 但是復(fù)雜點(diǎn)的處理還是不行,而且在運(yùn)行速度上,我測(cè)試了下我自己寫的,比這個(gè)快多了,1百萬(wàn)條數(shù)據(jù)大約也就2秒左右, 如果對(duì)速度有要求的話,我們可以使用多線程進(jìn)行分割,比如1千萬(wàn)條數(shù)據(jù),那么我開10個(gè)線程,1個(gè)線程執(zhí)行100萬(wàn)條數(shù)據(jù),所有線程執(zhí)行完畢后在按照順序拼接到一起,這樣1千萬(wàn)條數(shù)據(jù)也就最多3~5秒執(zhí)行完畢
代碼樣例
package com.file.csv;
import com.date.LocalDateUtils;
import lombok.Data;
import lombok.SneakyThrows;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
/**
* 對(duì)象轉(zhuǎn)csv格式
*
* @describe
* 1百萬(wàn)數(shù)據(jù)測(cè)試 2~3秒
* 調(diào)用順序如下(根據(jù)情況自行選擇)
* String s = ObjToCSV.create(userDatas)
* .fieldsAll() //轉(zhuǎn)換全部列
* .addIncludeFields() //只包含某些列
* .addExcludeFields("roleData") //排除某些列
* .addHead() //添加頭部字段
* .addContent() //一個(gè)對(duì)象(一行)
* .addContents() //多個(gè)對(duì)象(多行)
* .addEnding((data)->{ //結(jié)尾說明
* JSONObject jsonObject = new JSONObject();
* jsonObject.put("count",data.getNumber());
* jsonObject.put("time",data.getCreateDate());
* return jsonObject.toJSONString();
* })
* .ToString(); //結(jié)果
*/
@Data
public class ObjToCSV<T> {
private String separator = "\u0001|\u0001"; //默認(rèn)分隔符
private StringBuilder str = new StringBuilder();
private T object;
private List<T> objects;
private List<String> excludeFields = new ArrayList<String>(100) {{
add("serialVersionUID");
}};
private List<String> includeFields = new ArrayList<String>(100);
private boolean fieldsAll = false;
private int number;//多少行一共
//日期串 20220617204504
private String createDate=LocalDateUtils.getLocalDateTimeStr1() ;
private ObjToCSV(T object, String separator) {
this.object = object;
this.separator = separator;
//行數(shù)
this.number=1;
}
private ObjToCSV(T object) {
this.object = object;
//行數(shù)
this.number=1;
}
private ObjToCSV(List<T> objects) {
if (objects.isEmpty()) {
throw new NullPointerException("不能是空");
}
this.object = objects.get(0);
this.objects = objects;
//行數(shù)
this.number=objects.size();
}
private ObjToCSV(List<T> objects, String separator) {
if (objects.isEmpty()) {
throw new NullPointerException("不能是空");
}
this.object = objects.get(0);
this.objects = objects;
this.separator = separator;
//行數(shù)
this.number=objects.size();
}
// 排除和包含都有,那么以包含的為主
private boolean decideFields(String fieldName) {
//包含
if (includeFields.contains(fieldName)) {
return false;
}
//排除
if (excludeFields.contains(fieldName)) {
return true;
}
// 開啟全部放行
if (fieldsAll) {
return false;
}
//默認(rèn)攔截全部
return true;
}
public static <T> ObjToCSV<T> create(T object, String separator) {
return new ObjToCSV<T>(object, separator);
}
public static <T> ObjToCSV<T> create(T object) {
return new ObjToCSV<T>(object);
}
public static <T> ObjToCSV<T> create(List<T> object, String separator) {
return new ObjToCSV<T>(object, separator);
}
public static <T> ObjToCSV<T> create(List<T> object) {
return new ObjToCSV<T>(object);
}
//全部放行
public ObjToCSV<T> fieldsAll() {
fieldsAll = true;
return this;
}
//包含
public ObjToCSV<T> addIncludeFields(String... fieldName) {
includeFields.addAll(Arrays.asList(fieldName));
return this;
}
//排除
public ObjToCSV<T> addExcludeFields(String... fieldName) {
excludeFields.addAll(Arrays.asList(fieldName));
return this;
}
//添加頭部
public ObjToCSV<T> addHead() {
StringBuilder str1 = new StringBuilder();
Class<?> aClass = this.object.getClass();
Field[] fields = aClass.getDeclaredFields();
int length = fields.length;
for (int i = 0; i < length; i++) {
Field field = fields[i];
field.setAccessible(true);
if (decideFields(field.getName())) {
continue;
}
str1.append(field.getName()).append(separator);
}
int length1 = separator.length();
String substring = str1.substring(0, str1.length() - length1);
this.str.append(substring + "\n");
return this;
}
//在結(jié)尾補(bǔ)充自定義的描述
public ObjToCSV<T> addEnding(Function<ObjToCSV,String> functor){
String apply = functor.apply( this);
this.str.append(apply);
return this;
}
//將對(duì)象轉(zhuǎn)換為CSV格式字符串
@SneakyThrows
public ObjToCSV<T> addContent() {
StringBuilder str1 = new StringBuilder();
Class<?> aClass = this.object.getClass();
Field[] fields = aClass.getDeclaredFields();
int length = fields.length;
for (int i = 0; i < length; i++) {
Field field = fields[i];
field.setAccessible(true);
if (decideFields(field.getName())) {
continue;
}
Object o = field.get(object);
String value = "";
if (o != null) {
value = String.valueOf(o);
}
str1.append(value).append(separator);
}
int length1 = separator.length();
String substring = str1.substring(0, str1.length() - length1);
this.str.append(substring + "\n");
return this;
}
//將多個(gè)對(duì)象轉(zhuǎn)換為csv格式
public ObjToCSV<T> addContents() {
for (T t : this.objects) {
this.object=t;
addContent();
}
return this;
}
//將結(jié)果輸出為字符串
public String ToString() {
return str.toString();
}
}測(cè)試樣例
package com.file;
import com.alibaba.fastjson.JSONObject;
import com.data.RandomUserData;
import com.entity.UserData;
import com.file.csv.ObjToCSV;
import com.file.csv.ObjToCSV;
import com.function.impl.CodeStartAndStopTimeUtil;
import lombok.SneakyThrows;
import org.junit.Test;
import java.util.List;
public class ObjToCSVTest {
//單個(gè)對(duì)象
@Test
public void show1(){
UserData userOne = RandomUserData.getUserOne();
String s = ObjToCSV.create(userOne)
.fieldsAll()
// .addIncludeFields()
.addExcludeFields("roleData")
// .addHead()
.addContent()
// .addContents()
.addEnding((data)->{
JSONObject jsonObject = new JSONObject();
jsonObject.put("count",data.getNumber());
jsonObject.put("time",data.getCreateDate());
jsonObject.put("separator",data.getSeparator());
return jsonObject.toJSONString();
})
.ToString();
System.out.println(s);
}
//多個(gè)對(duì)象,可以使用自定義分隔符
@Test
public void show2(){
UserData userOne = RandomUserData.getUserOne();
String s = ObjToCSV.create(userOne,"|")
.fieldsAll()
.addExcludeFields("roleData")
.addContent()
.addEnding((data)->{
JSONObject jsonObject = new JSONObject();
jsonObject.put("count",data.getNumber());
jsonObject.put("time",data.getCreateDate());
jsonObject.put("separator",data.getSeparator());
return jsonObject.toJSONString();
})
.ToString();
System.out.println(s);
}
//排除不顯示的,其他都顯示
@Test
public void show3(){
List<UserData> userDatas = RandomUserData.getUserDatas(10);
String s = ObjToCSV.create(userDatas,"|")
.fieldsAll()//顯示全部字段
.addExcludeFields("roleData")//排除指定字段
.addHead()
.addContents()
.addEnding((data)->{
JSONObject jsonObject = new JSONObject();
jsonObject.put("count",data.getNumber());
jsonObject.put("time",data.getCreateDate());
jsonObject.put("separator",data.getSeparator());
return jsonObject.toJSONString();
})
.ToString();
System.out.println(s);
}
//只包含指定字段 ,其他都不顯示
@Test
public void show4(){
List<UserData> userDatas = RandomUserData.getUserDatas(10);
String s = ObjToCSV.create(userDatas,"|")
.addIncludeFields("id","name")
.addHead() //添加頭部
.addContents() //添加內(nèi)容
.addEnding((data)->{ //添加結(jié)尾信息
JSONObject jsonObject = new JSONObject();
jsonObject.put("count",data.getNumber());
jsonObject.put("time",data.getCreateDate());
jsonObject.put("separator",data.getSeparator());
return jsonObject.toJSONString();
})
.ToString();
System.out.println(s);
}
//內(nèi)容
@Test
public void show5(){
List<UserData> userDatas = RandomUserData.getUserDatas(10);
String s = ObjToCSV.create(userDatas,"|")
.fieldsAll()
.addExcludeFields("roleData")//排除指定字段
.addContents() //添加內(nèi)容
.ToString();
System.out.println(s);
}
@SneakyThrows
public static void main(String[] args) {
List<UserData> userDatas = RandomUserData.getUserDatas(100);
String s = ObjToCSV.create(userDatas)
.fieldsAll()
// .addIncludeFields()
.addExcludeFields("roleData")
// .addHead()
// .addContent()
.addContents()
.addEnding((data)->{
JSONObject jsonObject = new JSONObject();
jsonObject.put("count",data.getNumber());
jsonObject.put("time",data.getCreateDate());
return jsonObject.toJSONString();
})
.ToString();
System.out.println(s);
}
}到此這篇關(guān)于Java實(shí)現(xiàn)對(duì)象轉(zhuǎn)CSV格式的文章就介紹到這了,更多相關(guān)Java對(duì)象轉(zhuǎn)CSV內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
SpringBoot+Ajax+redis實(shí)現(xiàn)隱藏重要接口地址的方法
這篇文章主要介紹了SpringBoot+Ajax+redis實(shí)現(xiàn)隱藏重要接口地址,本篇文章主要講訴使用SpringBoot項(xiàng)目配合Ajax和redis實(shí)現(xiàn)隱藏重要接口地址,這里我以隱藏秒殺地址為例,需要的朋友可以參考下2024-03-03
Java中字符串String的+和+=及循環(huán)操作String原理詳解
Java編譯器在編譯時(shí)對(duì)String的+和+=操作會(huì)創(chuàng)建StringBuilder對(duì)象來進(jìn)行字符串的拼接,下面這篇文章主要給大家介紹了關(guān)于Java中字符串String的+和+=及循環(huán)操作String原理的相關(guān)資料,需要的朋友可以參考下2023-01-01
解決Java中socket使用getInputStream()阻塞問題
這篇文章主要介紹了解決Java中socket使用getInputStream()阻塞問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-12-12
詳解java中的互斥鎖信號(hào)量和多線程等待機(jī)制
這篇文章主要介紹了Java編程中的互斥鎖,信號(hào)量和多線程等待機(jī)制實(shí)例詳解,簡(jiǎn)單介紹了互斥鎖和信號(hào)量的區(qū)別,需要的朋友可以了解下。2017-09-09
java如何通過FileOutputStream字節(jié)流向文件中寫數(shù)據(jù)
這篇文章主要介紹了java如何通過FileOutputStream字節(jié)流向文件中寫數(shù)據(jù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-12-12

