Simple and easy to use java import excel csv tool class
Annotation class
package com.wl.poi.read.annotation;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Created by wl on 2018/10/22.
*/
@Target({ElementType.FIELD,ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ImportAnnotation {
int sheetIndex() default 0;
int rowIndex() default 1;
int cellIndex() default 100;
String method() default "";
int length() default 0;
Class type() default String.class;
}
Abstract class
package com.wl.poi.read.util;
import java.util.Iterator;
import java.util.List;
/**
* Created by wl on 2018/10/22.
*/
public abstract class ImportHelper<T> implements Iterator<T> {
public abstract int getTotalRowsNum();
public abstract List<T> getRows();
public abstract void close();
}
Tools
package com.wl.poi.read.util;
import com.wl.poi.read.annotation.ImportAnnotation;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
/**
* Created by wl on 2018/10/22.
*/
public class ImportUtil<T>{
private static final Logger LOGGER = LoggerFactory.getLogger(ImportUtil.class);
//========================================================excel
private Workbook workbook;
private int startRowIndex;
private int startSheetIndex;
private int totalSheets;
//========================================================csv
private CSVParser csvParser;
private Class<T> importClass;
private Method cacheMethods[];
private Class type[];
public ImportUtil(Class<T> importClass) throws NoSuchMethodException {
if(importClass == null){
throw new NullPointerException("");
}
this.importClass = importClass;
this.init(importClass);
}
//.xlsx
public ImportHelper<T> readExcel(InputStream is) throws IOException {
this.workbook = new XSSFWorkbook(is);
this.totalSheets = this.workbook.getNumberOfSheets();
return new ExcelIterator();
}
//.xls
public ImportHelper<T> readExcel2003(InputStream is) throws IOException {
this.workbook = new HSSFWorkbook(is);
this.totalSheets = this.workbook.getNumberOfSheets();
return new ExcelIterator();
}
public ImportHelper<T> readCSV(InputStream is,Charset charset,CSVFormat format)throws IOException{
csvParser = CSVParser.parse(is, charset, format);
return new CSVIterator();
}
public ImportHelper<T> readCSV(InputStream is)throws IOException{
return readCSV(is, Charset.defaultCharset(), CSVFormat.EXCEL);
}
private void init(Class<?> importClass) throws NoSuchMethodException {
ImportAnnotation annotation = importClass.getDeclaredAnnotation(ImportAnnotation.class);
{
// this.sheetIndex = annotation.sheetIndex();
// this.rowIndex = annotation.rowIndex();
this.cacheMethods = new Method[annotation.length()];
this.type = new Class[annotation.length()];
this.startRowIndex = annotation.rowIndex();
this.startSheetIndex = annotation.sheetIndex();
}
Field[] fields = importClass.getDeclaredFields();
for(Field field : fields){
annotation = field.getAnnotation(ImportAnnotation.class);
this.type[annotation.cellIndex()] = annotation.type();
this.cacheMethods[annotation.cellIndex()] = importClass.getMethod(annotation.method(),annotation.type());
}
}
private void closeWorkBook(){
try {
this.workbook.close();
} catch (IOException e) {
LOGGER.error("close workBook error",e);
}
}
private void closeCsv(){
try {
csvParser.close();
} catch (IOException e) {
LOGGER.error("close csvParse error",e);
}
}
private class ExcelIterator extends ImportHelper<T>{
private int sheetIndex;
private int rowIndex;
private int cellIndex;
private ExcelIterator(){
this.sheetIndex = startSheetIndex;
this.rowIndex = startRowIndex;
}
@Override
public boolean hasNext() {
if(workbook == null){
return false;
}
if(this.sheetIndex <= workbook.getNumberOfSheets() - 1){
// 只有一个sheet 或者最后一个sheet
if(workbook.getNumberOfSheets() == 1 || workbook.getNumberOfSheets() - 1 == this.sheetIndex){
int lastRow = workbook.getSheetAt(this.sheetIndex).getPhysicalNumberOfRows();
return this.rowIndex < lastRow;
}
return true;
}
return false;
}
@Override
public T next() {
Sheet sheet = workbook.getSheetAt(this.sheetIndex);
Row row = sheet.getRow(this.rowIndex);
try {
if(row != null) {
T obj = importClass.newInstance();
for (int i = 0; i < cacheMethods.length; i++) {
this.cellIndex = i;
Cell cell = row.getCell(i);
if (cell != null) {
cacheMethods[i].invoke(obj, getCellValue(cell, type[i]));
}
}
return obj;
}
} catch (Exception e) {
LOGGER.error("第:{} 个sheet 第:{} 个 row 第:{} 个 cell 解析成类:{} 方法:{} 类型:{} 失败"
,this.sheetIndex +1
,this.rowIndex + 1
,this.cellIndex + 1
,importClass.getName()
,cacheMethods[this.cellIndex].getName()
,type[this.cellIndex].getName()
,e.getMessage());
}finally {
//最后增加index
if (this.rowIndex >= sheet.getPhysicalNumberOfRows() - 1) { //sheet 的最后一个row
this.sheetIndex++;
this.rowIndex = startRowIndex; //重置为temp
} else {
this.rowIndex++;
}
}
return null;
}
@Override
public int getTotalRowsNum() {
int total = 0;
if(workbook != null) {
for (int i = 0; i < totalSheets; i++) {
total += workbook.getSheetAt(i).getPhysicalNumberOfRows() - startRowIndex;
}
}
return total;
}
@Override
public List<T> getRows() {
this.sheetIndex = startSheetIndex;
this.rowIndex = startRowIndex;
List<T> eList = new ArrayList<>();
while (hasNext()){
eList.add(next());
}
return eList;
}
@Override
public void close() {
closeWorkBook();
}
private Object getCellValue(Cell cell, Class type){
int cellType = cell.getCellType();
if(cellType == 0){ //数字
if(type == Date.class){ //日期特殊处理
return cell.getDateCellValue();
}
return getJavaValue(type,cell.getNumericCellValue() + "");
}else if(cellType == 4){
return getJavaValue(type,cell.getBooleanCellValue() + "");
}
return cell.getStringCellValue();
}
private Object getJavaValue(Class type, String s) {
if(type == Byte.class){
return (byte)Double.parseDouble(s);
}else if(type == Short.class){
return (short) Double.parseDouble(s);
}else if(type == Integer.class){
return (int)Double.parseDouble(s);
}else if(type == Long.class){
return (long)Double.parseDouble(s);
}else if(type == Float.class){
return (float)Double.parseDouble(s);
}else if(type == Double.class){ //数值类型
return Double.parseDouble(s);
}else if(type == Boolean.class){
return Boolean.parseBoolean(s);
}else{
return s;
}
}
}
private class CSVIterator extends ImportHelper<T>{
private int rowIndex = startRowIndex;
private int cellIndex;
private Iterator<CSVRecord> iterator = csvParser.iterator();
@Override
public void close() {
closeCsv();
}
@Override
public boolean hasNext() {
return iterator.hasNext();
}
@Override
public T next() {
CSVRecord csvRecord = iterator.next();
if(csvParser.getCurrentLineNumber() <= startRowIndex){ //第一行
if(hasNext()){
csvRecord = iterator.next();
}else{
return null;
}
}
try {
T t = importClass.newInstance();
for (int i = 0; i < cacheMethods.length; i++) {
this.cellIndex = i;
cacheMethods[i].invoke(t,getJavaValue(type[i],csvRecord.get(i)));
}
return t;
}catch (Exception e){
LOGGER.error("第:{} 个 row 第:{} 个 cell 解析成类:{} 方法:{} 类型:{} 失败"
,this.rowIndex + 1
,this.cellIndex + 1
,importClass.getName()
,cacheMethods[this.cellIndex].getName()
,type[this.cellIndex].getName()
,e.getMessage());
}finally {
this.rowIndex++;
}
return null;
}
private Object getJavaValue(Class type, String s) {
if(type == Byte.class){
return Byte.parseByte(s);
}else if(type == Short.class){
return Short.parseShort(s);
}else if(type == Integer.class){
return Integer.parseInt(s);
}else if(type == Long.class){
return Long.parseLong(s);
}else if(type == Float.class){
return Float.parseFloat(s);
}else if(type == Double.class){ //数值类型
return Double.parseDouble(s);
}else if(type == Boolean.class){
return Boolean.valueOf(s);
}else{
return s;
}
}
@Override
public int getTotalRowsNum() {
return (int)csvParser.getRecordNumber();
}
@Override
public List<T> getRows() {
iterator = csvParser.iterator();
List<T> tList = new ArrayList<>();
while (hasNext()){
tList.add(next());
}
return tList;
}
}
}
rely
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.25</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-csv -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
<version>1.5</version>
</dependency>
javabean
package com.wl.poi.read.model;
import com.wl.poi.read.annotation.ImportAnnotation;
/**
* Created by wl on 2018/10/26.
*/
@ImportAnnotation(length = 5)
public class User {
@ImportAnnotation(method = "setId" , type = Integer.class , cellIndex = 0)
private Integer id;
@ImportAnnotation(method = "setName" , type = String.class , cellIndex = 1)
private String name;
@ImportAnnotation(method = "setAge" , type = Integer.class , cellIndex = 2)
private Integer age;
@ImportAnnotation(method = "setEmail" , type = String.class , cellIndex = 3)
private String email;
@ImportAnnotation(method = "setMobile" , type = String.class , cellIndex = 4)
private String mobile;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getMobile() {
return mobile;
}
public void setMobile(String mobile) {
this.mobile = mobile;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", email='" + email + '\'' +
", mobile='" + mobile + '\'' +
'}';
}
}
excel
id | first name | age | mailbox | phone |
1 | Zhang San | 18 | ***@qq.com | 138*** |
2 | Li Si | 18 | [email protected] | 158*** |
Test code
@Test
public void testImportExcel() throws Exception {
ImportUtil<User> importExcelUtil = new ImportUtil<>(User.class);
File file = new File("C:\\Users\\wl\\Desktop\\用户.xlsx");
ImportHelper<User> helper;
helper = importExcelUtil.readExcel(new FileInputStream(file));
List<User> userList = new ArrayList<>();
while (helper.hasNext()){
userList.add(helper.next());
}
System.out.println(userList);
}
@Test
public void testImportCSV() throws Exception {
ImportUtil<User> importExcelUtil = new ImportUtil<>(User.class);
File file = new File("C:\\Users\\wl\\Desktop\\用户.csv");
ImportHelper<User> helper;
helper = importExcelUtil.readCSV(new FileInputStream(file));
List<User> userList = new ArrayList<>();
while (helper.hasNext()){
userList.add(helper.next());
}
System.out.println(userList);
}
Print result
Use fast-csv import csv file tool
package com.wl.poi.read.util;
import com.wl.poi.read.annotation.ImportAnnotation;
import de.siegmar.fastcsv.reader.CsvContainer;
import de.siegmar.fastcsv.reader.CsvReader;
import de.siegmar.fastcsv.reader.CsvRow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
/**
* Created by wl on 2018/11/7.
*/
public class ImportCsvUtil<T>{
private static final Logger LOGGER = LoggerFactory.getLogger(ImportCsvUtil.class);
private CsvContainer csvContainer;
private Class types[];
private Reader reader;
private Method cacheMethods[];
private Class<T> importClass;
private Integer startRowIndex;
public ImportCsvUtil(Class<T> importClass) throws Exception{
if(importClass == null){
throw new NullPointerException("");
}
this.importClass = importClass;
this.init(importClass);
}
public ImportHelper<T> readCSV(InputStream is) throws IOException {
// return readCSV(is,Charset.defaultCharset());
return readCSV(is,Charset.forName("GBK"));
}
public ImportHelper<T> readCSV(InputStream is,Charset charset) throws IOException {
CsvReader csvReader = new CsvReader();
csvReader.setContainsHeader(false);
csvReader.setSkipEmptyRows(true);
this.reader = new InputStreamReader(is,charset);
this.csvContainer = csvReader.read(reader);
return new CSVIterator();
}
private void init(Class<?> importClass) throws NoSuchMethodException {
ImportAnnotation annotation = importClass.getDeclaredAnnotation(ImportAnnotation.class);
{
this.cacheMethods = new Method[annotation.length()];
this.types = new Class[annotation.length()];
this.startRowIndex = annotation.rowIndex();
}
Field[] fields = importClass.getDeclaredFields();
for(Field field : fields){
annotation = field.getAnnotation(ImportAnnotation.class);
this.types[annotation.cellIndex()] = annotation.type();
this.cacheMethods[annotation.cellIndex()] = importClass.getMethod(annotation.method(),annotation.type());
}
}
private void closeCsv(){
try {
this.reader.close();
} catch (IOException e) {
LOGGER.error("close reader error",e);
}
}
private class CSVIterator extends ImportHelper<T>{
int rowIndex = startRowIndex;
int cellIndex;
int count = csvContainer.getRowCount();
CsvRow row;
@Override
public boolean hasNext() {
return this.rowIndex < this.count;
}
@Override
public T next() {
row = csvContainer.getRow(rowIndex);
try {
T t = importClass.newInstance();
for (int i = 0; i < cacheMethods.length; i++) {
this.cellIndex = i;
cacheMethods[i].invoke(t,getJavaValue(types[i],row.getField(i)));
}
return t;
}catch (Exception e){
LOGGER.error("第:{} 个 row 第:{} 个 cell 解析成类:{} 方法:{} 类型:{} 失败"
,this.rowIndex + 1
,this.cellIndex + 1
,importClass.getName()
,cacheMethods[this.cellIndex].getName()
,types[this.cellIndex].getName()
,e.getMessage());
}finally {
rowIndex++;
}
return null;
}
@Override
public int getTotalRowsNum() {
return count;
}
@Override
public List<T> getRows() {
this.rowIndex = startRowIndex;
List<T> tList = new ArrayList<>();
this.forEachRemaining(tList::add);
return tList;
}
@Override
public void close() {
closeCsv();
}
private Object getJavaValue(Class type, String s) {
if(type == Byte.class){
return Byte.parseByte(s);
}else if(type == Short.class){
return Short.parseShort(s);
}else if(type == Integer.class){
return Integer.parseInt(s);
}else if(type == Long.class){
return Long.parseLong(s);
}else if(type == Float.class){
return Float.parseFloat(s);
}else if(type == Double.class){ //数值类型
return Double.parseDouble(s);
}else if(type == Boolean.class){
return Boolean.valueOf(s);
}
return s;
}
}
}
Need to rely on
<!-- https://mvnrepository.com/artifact/de.siegmar/fastcsv -->
<dependency>
<groupId>de.siegmar</groupId>
<artifactId>fastcsv</artifactId>
<version>1.0.3</version>
</dependency>