From 8ded0abc5f906d2d918e88c1b359ba742a091c27 Mon Sep 17 00:00:00 2001 From: Jiaju Zhuang Date: Wed, 8 Sep 2021 18:43:50 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90csv=20=E4=B9=A6=E5=86=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../excel/analysis/ExcelAnalyserImpl.java | 26 ++- .../analysis/csv/CsvExcelReadExecutor.java | 112 +++++++++++++ .../excel/context/AnalysisContextImpl.java | 9 +- .../excel/context/csv/CsvReadContext.java | 26 +++ .../context/csv/DefaultCsvReadContext.java | 29 ++++ .../metadata/holder/AbstractReadHolder.java | 2 + .../read/metadata/holder/ReadSheetHolder.java | 2 + .../metadata/holder/ReadWorkbookHolder.java | 156 +----------------- .../holder/csv/CsvReadSheetHolder.java | 20 +++ .../holder/csv/CsvReadWorkbookHolder.java | 25 +++ .../easyexcel/test/temp/csv/CsvReadTest.java | 22 +++ 11 files changed, 268 insertions(+), 161 deletions(-) create mode 100644 src/main/java/com/alibaba/excel/analysis/csv/CsvExcelReadExecutor.java create mode 100644 src/main/java/com/alibaba/excel/context/csv/CsvReadContext.java create mode 100644 src/main/java/com/alibaba/excel/context/csv/DefaultCsvReadContext.java create mode 100644 src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadSheetHolder.java create mode 100644 src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadWorkbookHolder.java diff --git a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java index e049dbfc..743daab9 100644 --- a/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java +++ b/src/main/java/com/alibaba/excel/analysis/ExcelAnalyserImpl.java @@ -3,18 +3,12 @@ package com.alibaba.excel.analysis; import java.io.InputStream; import java.util.List; -import org.apache.commons.collections4.CollectionUtils; -import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; -import org.apache.poi.poifs.crypt.Decryptor; -import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; -import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.util.IOUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import com.alibaba.excel.analysis.csv.CsvExcelReadExecutor; import com.alibaba.excel.analysis.v03.XlsSaxAnalyser; import com.alibaba.excel.analysis.v07.XlsxSaxAnalyser; import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.context.csv.CsvReadContext; +import com.alibaba.excel.context.csv.DefaultCsvReadContext; import com.alibaba.excel.context.xls.DefaultXlsReadContext; import com.alibaba.excel.context.xls.XlsReadContext; import com.alibaba.excel.context.xlsx.DefaultXlsxReadContext; @@ -32,6 +26,15 @@ import com.alibaba.excel.util.FileUtils; import com.alibaba.excel.util.NumberDataFormatterUtils; import com.alibaba.excel.util.StringUtils; +import org.apache.commons.collections4.CollectionUtils; +import org.apache.poi.hssf.record.crypto.Biff8EncryptionKey; +import org.apache.poi.poifs.crypt.Decryptor; +import org.apache.poi.poifs.filesystem.DocumentFactoryHelper; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; +import org.apache.poi.util.IOUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * @author jipengfei */ @@ -98,6 +101,11 @@ public class ExcelAnalyserImpl implements ExcelAnalyser { analysisContext = xlsxReadContext; excelReadExecutor = new XlsxSaxAnalyser(xlsxReadContext, null); break; + case CSV: + CsvReadContext csvReadContext = new DefaultCsvReadContext(readWorkbook, ExcelTypeEnum.CSV); + analysisContext = csvReadContext; + excelReadExecutor = new CsvExcelReadExecutor(csvReadContext); + break; default: break; } diff --git a/src/main/java/com/alibaba/excel/analysis/csv/CsvExcelReadExecutor.java b/src/main/java/com/alibaba/excel/analysis/csv/CsvExcelReadExecutor.java new file mode 100644 index 00000000..6f1353ca --- /dev/null +++ b/src/main/java/com/alibaba/excel/analysis/csv/CsvExcelReadExecutor.java @@ -0,0 +1,112 @@ +package com.alibaba.excel.analysis.csv; + +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import com.alibaba.excel.analysis.ExcelReadExecutor; +import com.alibaba.excel.context.csv.CsvReadContext; +import com.alibaba.excel.enums.CellDataTypeEnum; +import com.alibaba.excel.enums.RowTypeEnum; +import com.alibaba.excel.exception.ExcelAnalysisException; +import com.alibaba.excel.metadata.Cell; +import com.alibaba.excel.metadata.data.ReadCellData; +import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.read.metadata.holder.ReadRowHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadWorkbookHolder; +import com.alibaba.excel.util.SheetUtils; + +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.collections4.MapUtils; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVRecord; + +/** + * azz + * + * @author zhuangjiaju + */ +@Slf4j +public class CsvExcelReadExecutor implements ExcelReadExecutor { + + private List sheetList; + private CsvReadContext csvReadContext; + + public CsvExcelReadExecutor(CsvReadContext csvReadContext) { + this.csvReadContext = csvReadContext; + sheetList = new ArrayList<>(); + ReadSheet readSheet = new ReadSheet(); + sheetList.add(readSheet); + readSheet.setSheetNo(0); + } + + @Override + public List sheetList() { + return sheetList; + } + + @Override + public void execute() { + Iterable parseRecords; + try { + parseRecords = parseRecords(); + } catch (IOException e) { + throw new ExcelAnalysisException(e); + } + for (ReadSheet readSheet : sheetList) { + readSheet = SheetUtils.match(readSheet, csvReadContext); + if (readSheet == null) { + continue; + } + csvReadContext.currentSheet(readSheet); + + int rowIndex = 0; + for (CSVRecord record : parseRecords) { + + dealRecord(record, rowIndex++); + } + // The last sheet is read + csvReadContext.analysisEventProcessor().endSheet(csvReadContext); + } + } + + private Iterable parseRecords() throws IOException { + CsvReadWorkbookHolder csvReadWorkbookHolder = csvReadContext.csvReadWorkbookHolder(); + CSVFormat csvFormat = csvReadWorkbookHolder.getCsvFormat(); + + if (csvReadWorkbookHolder.getMandatoryUseInputStream()) { + return csvFormat.parse(new InputStreamReader(csvReadWorkbookHolder.getInputStream())); + } + if (csvReadWorkbookHolder.getFile() != null) { + return csvFormat.parse(new FileReader(csvReadWorkbookHolder.getFile())); + } + return csvFormat.parse(new InputStreamReader(csvReadWorkbookHolder.getInputStream())); + } + + private void dealRecord(CSVRecord record, int rowIndex) { + Map cellMap = new LinkedHashMap<>(); + Iterator cellIterator = record.iterator(); + int cellIndex = 0; + while (cellIterator.hasNext()) { + String cellString = cellIterator.next(); + ReadCellData readCellData = new ReadCellData<>(); + readCellData.setType(CellDataTypeEnum.STRING); + readCellData.setStringValue(cellString); + cellMap.put(cellIndex++, readCellData); + } + + RowTypeEnum rowType = MapUtils.isEmpty(cellMap) ? RowTypeEnum.EMPTY : RowTypeEnum.DATA; + ReadRowHolder readRowHolder = new ReadRowHolder(rowIndex, rowType, + csvReadContext.readWorkbookHolder().getGlobalConfiguration(), cellMap); + csvReadContext.readRowHolder(readRowHolder); + + csvReadContext.csvReadSheetHolder().setCellMap(cellMap); + csvReadContext.csvReadSheetHolder().setRowIndex(rowIndex); + csvReadContext.analysisEventProcessor().endRow(csvReadContext); + } +} diff --git a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java index 7aeba321..4edaef37 100644 --- a/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java +++ b/src/main/java/com/alibaba/excel/context/AnalysisContextImpl.java @@ -10,6 +10,8 @@ import com.alibaba.excel.read.metadata.holder.ReadHolder; import com.alibaba.excel.read.metadata.holder.ReadRowHolder; import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadSheetHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.xls.XlsReadSheetHolder; import com.alibaba.excel.read.metadata.holder.xls.XlsReadWorkbookHolder; import com.alibaba.excel.read.metadata.holder.xlsx.XlsxReadSheetHolder; @@ -57,6 +59,9 @@ public class AnalysisContextImpl implements AnalysisContext { case XLSX: readWorkbookHolder = new XlsxReadWorkbookHolder(readWorkbook); break; + case CSV: + readWorkbookHolder = new CsvReadWorkbookHolder(readWorkbook); + break; default: break; } @@ -76,6 +81,9 @@ public class AnalysisContextImpl implements AnalysisContext { case XLSX: readSheetHolder = new XlsxReadSheetHolder(readSheet, readWorkbookHolder); break; + case CSV: + readSheetHolder = new CsvReadSheetHolder(readSheet, readWorkbookHolder); + break; default: break; } @@ -134,7 +142,6 @@ public class AnalysisContextImpl implements AnalysisContext { } - @Override public ExcelTypeEnum getExcelType() { return readWorkbookHolder.getExcelType(); diff --git a/src/main/java/com/alibaba/excel/context/csv/CsvReadContext.java b/src/main/java/com/alibaba/excel/context/csv/CsvReadContext.java new file mode 100644 index 00000000..00bcd54a --- /dev/null +++ b/src/main/java/com/alibaba/excel/context/csv/CsvReadContext.java @@ -0,0 +1,26 @@ +package com.alibaba.excel.context.csv; + +import com.alibaba.excel.context.AnalysisContext; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadSheetHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadWorkbookHolder; + +/** + * A context is the main anchorage point of a ls xls reader. + * + * @author Jiaju Zhuang + **/ +public interface CsvReadContext extends AnalysisContext { + /** + * All information about the workbook you are currently working on. + * + * @return Current workbook holder + */ + CsvReadWorkbookHolder csvReadWorkbookHolder(); + + /** + * All information about the sheet you are currently working on. + * + * @return Current sheet holder + */ + CsvReadSheetHolder csvReadSheetHolder(); +} diff --git a/src/main/java/com/alibaba/excel/context/csv/DefaultCsvReadContext.java b/src/main/java/com/alibaba/excel/context/csv/DefaultCsvReadContext.java new file mode 100644 index 00000000..d8653a88 --- /dev/null +++ b/src/main/java/com/alibaba/excel/context/csv/DefaultCsvReadContext.java @@ -0,0 +1,29 @@ +package com.alibaba.excel.context.csv; + +import com.alibaba.excel.context.AnalysisContextImpl; +import com.alibaba.excel.read.metadata.ReadWorkbook; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadSheetHolder; +import com.alibaba.excel.read.metadata.holder.csv.CsvReadWorkbookHolder; +import com.alibaba.excel.support.ExcelTypeEnum; + +/** + * A context is the main anchorage point of a ls xls reader. + * + * @author Jiaju Zhuang + */ +public class DefaultCsvReadContext extends AnalysisContextImpl implements CsvReadContext { + + public DefaultCsvReadContext(ReadWorkbook readWorkbook, ExcelTypeEnum actualExcelType) { + super(readWorkbook, actualExcelType); + } + + @Override + public CsvReadWorkbookHolder csvReadWorkbookHolder() { + return (CsvReadWorkbookHolder)readWorkbookHolder(); + } + + @Override + public CsvReadSheetHolder csvReadSheetHolder() { + return (CsvReadSheetHolder)readSheetHolder(); + } +} diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java index 641b489f..ab6dfb72 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/AbstractReadHolder.java @@ -16,6 +16,7 @@ import com.alibaba.excel.read.metadata.property.ExcelReadHeadProperty; import com.alibaba.excel.util.ListUtils; import lombok.Data; +import lombok.NoArgsConstructor; /** * Read Holder @@ -23,6 +24,7 @@ import lombok.Data; * @author Jiaju Zhuang */ @Data +@NoArgsConstructor public abstract class AbstractReadHolder extends AbstractHolder implements ReadHolder { /** * Count the number of added heads when read sheet. diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java index 12cd7233..73b00e71 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadSheetHolder.java @@ -10,6 +10,7 @@ import com.alibaba.excel.metadata.data.ReadCellData; import com.alibaba.excel.read.metadata.ReadSheet; import lombok.Data; +import lombok.NoArgsConstructor; /** * sheet holder @@ -17,6 +18,7 @@ import lombok.Data; * @author Jiaju Zhuang */ @Data +@NoArgsConstructor public class ReadSheetHolder extends AbstractReadHolder { /** diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java index 375e32cc..6693467f 100644 --- a/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/ReadWorkbookHolder.java @@ -19,11 +19,16 @@ import com.alibaba.excel.read.metadata.ReadSheet; import com.alibaba.excel.read.metadata.ReadWorkbook; import com.alibaba.excel.support.ExcelTypeEnum; +import lombok.Data; +import lombok.NoArgsConstructor; + /** * Workbook holder * * @author Jiaju Zhuang */ +@Data +@NoArgsConstructor public class ReadWorkbookHolder extends AbstractReadHolder { /** @@ -171,157 +176,6 @@ public class ReadWorkbookHolder extends AbstractReadHolder { this.password = readWorkbook.getPassword(); } - public ReadWorkbook getReadWorkbook() { - return readWorkbook; - } - - public void setReadWorkbook(ReadWorkbook readWorkbook) { - this.readWorkbook = readWorkbook; - } - - public InputStream getInputStream() { - return inputStream; - } - - public void setInputStream(InputStream inputStream) { - this.inputStream = inputStream; - } - - public File getFile() { - return file; - } - - public void setFile(File file) { - this.file = file; - } - - public Boolean getAutoCloseStream() { - return autoCloseStream; - } - - public void setAutoCloseStream(Boolean autoCloseStream) { - this.autoCloseStream = autoCloseStream; - } - - public ExcelTypeEnum getExcelType() { - return excelType; - } - - public void setExcelType(ExcelTypeEnum excelType) { - this.excelType = excelType; - } - - public Object getCustomObject() { - return customObject; - } - - public void setCustomObject(Object customObject) { - this.customObject = customObject; - } - - public Boolean getIgnoreEmptyRow() { - return ignoreEmptyRow; - } - - public void setIgnoreEmptyRow(Boolean ignoreEmptyRow) { - this.ignoreEmptyRow = ignoreEmptyRow; - } - - public ReadCache getReadCache() { - return readCache; - } - - public void setReadCache(ReadCache readCache) { - this.readCache = readCache; - } - - public ReadCacheSelector getReadCacheSelector() { - return readCacheSelector; - } - - public void setReadCacheSelector(ReadCacheSelector readCacheSelector) { - this.readCacheSelector = readCacheSelector; - } - - public Boolean getMandatoryUseInputStream() { - return mandatoryUseInputStream; - } - - public void setMandatoryUseInputStream(Boolean mandatoryUseInputStream) { - this.mandatoryUseInputStream = mandatoryUseInputStream; - } - - public File getTempFile() { - return tempFile; - } - - public void setTempFile(File tempFile) { - this.tempFile = tempFile; - } - - public Boolean getConvertAllFiled() { - return convertAllFiled; - } - - public void setConvertAllFiled(Boolean convertAllFiled) { - this.convertAllFiled = convertAllFiled; - } - - public Set getHasReadSheet() { - return hasReadSheet; - } - - public void setHasReadSheet(Set hasReadSheet) { - this.hasReadSheet = hasReadSheet; - } - - public Boolean getDefaultReturnMap() { - return defaultReturnMap; - } - - public void setDefaultReturnMap(Boolean defaultReturnMap) { - this.defaultReturnMap = defaultReturnMap; - } - - public String getPassword() { - return password; - } - - public void setPassword(String password) { - this.password = password; - } - - public Set getExtraReadSet() { - return extraReadSet; - } - - public void setExtraReadSet(Set extraReadSet) { - this.extraReadSet = extraReadSet; - } - - public List getActualSheetDataList() { - return actualSheetDataList; - } - - public void setActualSheetDataList(List actualSheetDataList) { - this.actualSheetDataList = actualSheetDataList; - } - - public List getParameterSheetDataList() { - return parameterSheetDataList; - } - - public void setParameterSheetDataList(List parameterSheetDataList) { - this.parameterSheetDataList = parameterSheetDataList; - } - - public Boolean getReadAll() { - return readAll; - } - - public void setReadAll(Boolean readAll) { - this.readAll = readAll; - } @Override public HolderEnum holderType() { diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadSheetHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadSheetHolder.java new file mode 100644 index 00000000..d6bf6953 --- /dev/null +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadSheetHolder.java @@ -0,0 +1,20 @@ +package com.alibaba.excel.read.metadata.holder.csv; + +import com.alibaba.excel.read.metadata.ReadSheet; +import com.alibaba.excel.read.metadata.holder.ReadSheetHolder; +import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; + +import lombok.Data; + +/** + * sheet holder + * + * @author Jiaju Zhuang + */ +@Data +public class CsvReadSheetHolder extends ReadSheetHolder { + + public CsvReadSheetHolder(ReadSheet readSheet, ReadWorkbookHolder readWorkbookHolder) { + super(readSheet, readWorkbookHolder); + } +} diff --git a/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadWorkbookHolder.java b/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadWorkbookHolder.java new file mode 100644 index 00000000..4e8de41f --- /dev/null +++ b/src/main/java/com/alibaba/excel/read/metadata/holder/csv/CsvReadWorkbookHolder.java @@ -0,0 +1,25 @@ +package com.alibaba.excel.read.metadata.holder.csv; + +import com.alibaba.excel.read.metadata.ReadWorkbook; +import com.alibaba.excel.read.metadata.holder.ReadWorkbookHolder; +import com.alibaba.excel.support.ExcelTypeEnum; + +import lombok.Data; +import org.apache.commons.csv.CSVFormat; + +/** + * Workbook holder + * + * @author Jiaju Zhuang + */ +@Data +public class CsvReadWorkbookHolder extends ReadWorkbookHolder { + + private CSVFormat csvFormat; + + public CsvReadWorkbookHolder(ReadWorkbook readWorkbook) { + super(readWorkbook); + setExcelType(ExcelTypeEnum.CSV); + csvFormat = CSVFormat.DEFAULT; + } +} diff --git a/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java index 6fe42448..653eafc6 100644 --- a/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java +++ b/src/test/java/com/alibaba/easyexcel/test/temp/csv/CsvReadTest.java @@ -2,6 +2,7 @@ package com.alibaba.easyexcel.test.temp.csv; import java.io.File; import java.io.FileInputStream; +import java.io.FileReader; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Date; @@ -9,10 +10,12 @@ import java.util.List; import com.alibaba.easyexcel.test.util.TestFileUtil; import com.alibaba.excel.EasyExcel; +import com.alibaba.fastjson.JSON; import lombok.extern.slf4j.Slf4j; import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; +import org.apache.commons.csv.CSVRecord; import org.apache.poi.poifs.filesystem.FileMagic; import org.junit.Ignore; import org.junit.Test; @@ -33,6 +36,18 @@ public class CsvReadTest { printer.close(); } + @Test + public void read1() throws Exception { + Iterable records = CSVFormat.DEFAULT.parse( + new FileReader("/Users/zhuangjiaju/IdeaProjects/easyexcel/target/test-classes/csvWrite1.csv")); + for (CSVRecord record : records) { + String lastName = record.get(0); + String firstName = record.get(1); + log.info("row:{},{}", lastName, firstName); + } + + } + @Test public void csvWrite() throws Exception { // 写法1 @@ -40,6 +55,13 @@ public class CsvReadTest { // 这里 需要指定写用哪个class去写,然后写到第一个sheet,名字为模板 然后文件流会自动关闭 // 如果这里想使用03 则 传入excelType参数即可 EasyExcel.write(fileName, CsvData.class).sheet().doWrite(data()); + + // 读 + List list = EasyExcel.read(fileName).sheet(0).headRowNumber(0).doReadSync(); + log.info("数据:{}", list.size()); + for (Object data : list) { + log.info("返回数据:{}", JSON.toJSONString(data)); + } } @Test