From 6c9b0127086c117745ecad953eb93f394c21837a Mon Sep 17 00:00:00 2001 From: meiwei <309921330@qq.com> Date: Tue, 30 Aug 2022 21:39:21 +0800 Subject: [PATCH] =?UTF-8?q?perf[storage]:=20=E5=A2=9E=E5=8A=A0=E8=A7=A3?= =?UTF-8?q?=E6=9E=90csv=E6=96=87=E4=BB=B6=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- storage/pom.xml | 6 ++ .../storage/interpreter/ResourceReader.java | 9 +- .../storage/model/resource/ResourceData.java | 8 +- .../storage/model/resource/ResourceEnum.java | 2 + .../storage/model/resource/ResourceRow.java | 51 --------- .../com/zfoo/storage/util/CsvReaderUtils.java | 97 ++++++++++++++++++ ...ToJsonUtils.java => ExcelReaderUtils.java} | 35 +++---- .../com/zfoo/storage/ApplicationTest.java | 5 + .../java/com/zfoo/storage/StudentManager.java | 3 + .../com/zfoo/storage/excel/ExcelTest.java | 4 +- .../storage/resource/StudentCsvResource.java | 78 ++++++++++++++ .../src/test/resources/StudentResource.xlsx | Bin 10035 -> 0 bytes .../resources/excel/StudentCsvResource.csv | 7 ++ 13 files changed, 225 insertions(+), 80 deletions(-) delete mode 100644 storage/src/main/java/com/zfoo/storage/model/resource/ResourceRow.java create mode 100644 storage/src/main/java/com/zfoo/storage/util/CsvReaderUtils.java rename storage/src/main/java/com/zfoo/storage/util/{ExcelToJsonUtils.java => ExcelReaderUtils.java} (86%) create mode 100644 storage/src/test/java/com/zfoo/storage/resource/StudentCsvResource.java delete mode 100644 storage/src/test/resources/StudentResource.xlsx create mode 100644 storage/src/test/resources/excel/StudentCsvResource.csv diff --git a/storage/pom.xml b/storage/pom.xml index 9b0dad2b..bd710ade 100644 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -57,6 +57,7 @@ 1.2.51 4.1.2 + 1.9.0 3.27.0-GA 1.10.22 @@ -150,6 +151,11 @@ poi-ooxml ${poi.version} + + org.apache.commons + commons-csv + ${csv.version} + diff --git a/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java b/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java index ec40432a..d8627393 100644 --- a/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java +++ b/storage/src/main/java/com/zfoo/storage/interpreter/ResourceReader.java @@ -21,7 +21,8 @@ import com.zfoo.storage.model.anno.Id; import com.zfoo.storage.model.resource.ResourceData; import com.zfoo.storage.model.resource.ResourceEnum; import com.zfoo.storage.strategy.*; -import com.zfoo.storage.util.ExcelToJsonUtils; +import com.zfoo.storage.util.CsvReaderUtils; +import com.zfoo.storage.util.ExcelReaderUtils; import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.springframework.context.support.ConversionServiceFactoryBean; @@ -63,7 +64,9 @@ public class ResourceReader implements IResourceReader { if (resourceEnum == ResourceEnum.JSON) { resource = JsonUtils.string2Object(StringUtils.bytesToString(IOUtils.toByteArray(inputStream)), ResourceData.class); } else if (resourceEnum == ResourceEnum.EXCEL_XLS || resourceEnum == ResourceEnum.EXCEL_XLSX) { - resource = ExcelToJsonUtils.readResourceDataFromExcel(inputStream, clazz.getSimpleName()); + resource = ExcelReaderUtils.readResourceDataFromExcel(inputStream, clazz.getSimpleName()); + } else if (resourceEnum == ResourceEnum.CSV) { + resource = CsvReaderUtils.readResourceDataFromCSV(inputStream, clazz.getSimpleName()); } else { throw new RunException("不支持文件[{}]的配置类型[{}]", clazz.getSimpleName(), suffix); } @@ -76,7 +79,7 @@ public class ResourceReader implements IResourceReader { var iterator = resource.getRows().iterator(); // 从ROW_SERVER这行开始读取数据 while (iterator.hasNext()) { - var columns = iterator.next().getColumns(); + var columns = iterator.next(); var instance = ReflectionUtils.newInstance(clazz); for (var fieldInfo : fieldInfos) { diff --git a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceData.java b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceData.java index 3b1fdb11..23d683bc 100644 --- a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceData.java +++ b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceData.java @@ -27,9 +27,9 @@ public class ResourceData { // 配置表字段名 private List headers = new ArrayList<>(); // 配置表数据 - private List rows = new ArrayList<>(); + private List> rows = new ArrayList<>(); - public static ResourceData valueOf(String name, List headers, List rows) { + public static ResourceData valueOf(String name, List headers, List> rows) { var resourceData = new ResourceData(); resourceData.name = name; resourceData.headers = headers; @@ -53,11 +53,11 @@ public class ResourceData { this.headers = headers; } - public List getRows() { + public List> getRows() { return rows; } - public void setRows(List rows) { + public void setRows(List> rows) { this.rows = rows; } diff --git a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceEnum.java b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceEnum.java index 53e34e44..e203b875 100644 --- a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceEnum.java +++ b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceEnum.java @@ -33,6 +33,8 @@ public enum ResourceEnum { JSON("json"), + CSV("csv"), + ; private static Map typeMap = new HashMap<>(); diff --git a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceRow.java b/storage/src/main/java/com/zfoo/storage/model/resource/ResourceRow.java deleted file mode 100644 index 764661dc..00000000 --- a/storage/src/main/java/com/zfoo/storage/model/resource/ResourceRow.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (C) 2020 The zfoo Authors - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except - * in compliance with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed - * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and limitations under the License. - */ -package com.zfoo.storage.model.resource; - -import java.util.ArrayList; -import java.util.List; - -/** - * @author godotg - * @version 4.0 - */ -public class ResourceRow { - - private int row; - - private List columns = new ArrayList<>(); - - public static ResourceRow valueOf(int row, List columns) { - var resourceRow = new ResourceRow(); - resourceRow.row = row; - resourceRow.columns = columns; - return resourceRow; - } - - public int getRow() { - return row; - } - - public void setRow(int row) { - this.row = row; - } - - public List getColumns() { - return columns; - } - - public void setColumns(List columns) { - this.columns = columns; - } - -} diff --git a/storage/src/main/java/com/zfoo/storage/util/CsvReaderUtils.java b/storage/src/main/java/com/zfoo/storage/util/CsvReaderUtils.java new file mode 100644 index 00000000..f27dde9f --- /dev/null +++ b/storage/src/main/java/com/zfoo/storage/util/CsvReaderUtils.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2020 The zfoo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.zfoo.storage.util; + +import com.zfoo.protocol.exception.RunException; +import com.zfoo.protocol.util.StringUtils; +import com.zfoo.storage.model.resource.ResourceData; +import com.zfoo.storage.model.resource.ResourceHeader; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.util.*; + +/** + * @author meiwei666 + * @version 4.0 + */ +public class CsvReaderUtils { + + /** + * 构建配置表消息头 + * @param iterator + * @param fileName + * @return + */ + private static List getHeaders(Iterator iterator, String fileName) { + // 获取配置表的有效列名称,默认第一行就是字段名称 + var fieldRow = iterator.next(); + if (fieldRow == null) { + throw new RunException("无法获取资源[class:{}]的Excel文件的属性控制列", fileName); + } + //默认第二行字段类型 + var typeRow = iterator.next(); + if (typeRow == null) { + throw new RunException("无法获取资源[class:{}]的Excel文件的类型控制列", fileName); + } + var descRow = iterator.next(); + + List headers = new ArrayList<>(); + for (int i = 0; i < fieldRow.size(); i++) { + String fieldName = fieldRow.get(i); + if (fieldName == null) { + throw new RunException("{}列名不能为空,第{}列没有配置名字", fileName ,i + 1); + } + String filedType = typeRow.get(i); + if (filedType == null) { + throw new RunException("{}列类型不能为空,第{}列没有配置类型", fileName ,i + 1); + } +// String desc = descRecord.get(i); + headers.add(ResourceHeader.valueOf(fieldName, filedType, i )); + } + return headers; + } + + public static ResourceData readResourceDataFromCSV(InputStream input, String fileName){ + CSVParser records = parseCsv(input, fileName); + Iterator iter = records.iterator(); + List headers = getHeaders(iter, fileName); + List> rows = new ArrayList<>(); + while (iter.hasNext()) { + CSVRecord record = iter.next(); + List data = new ArrayList<>(); + for (ResourceHeader header : headers) { + String value = record.get(header.getIndex()); + if (StringUtils.isBlank(value)) { + value = StringUtils.EMPTY; + } + data.add(value); + } + rows.add(data); + } + return ResourceData.valueOf(fileName, headers, rows); + } + + private static CSVParser parseCsv(InputStream input, String fileName) { + try { + return CSVFormat.EXCEL.parse(new InputStreamReader(input)); + } catch (IOException e) { + throw new RunException("静态资源[{}]异常,无法读取文件", fileName); + } + } +} diff --git a/storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java b/storage/src/main/java/com/zfoo/storage/util/ExcelReaderUtils.java similarity index 86% rename from storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java rename to storage/src/main/java/com/zfoo/storage/util/ExcelReaderUtils.java index b5bcad67..41f70769 100644 --- a/storage/src/main/java/com/zfoo/storage/util/ExcelToJsonUtils.java +++ b/storage/src/main/java/com/zfoo/storage/util/ExcelReaderUtils.java @@ -20,25 +20,19 @@ import com.zfoo.protocol.util.StringUtils; import com.zfoo.storage.model.resource.ResourceData; import com.zfoo.storage.model.resource.ResourceEnum; import com.zfoo.storage.model.resource.ResourceHeader; -import com.zfoo.storage.model.resource.ResourceRow; -import org.apache.poi.ss.usermodel.Sheet; -import org.apache.poi.ss.usermodel.Workbook; -import org.apache.poi.ss.usermodel.WorkbookFactory; +import org.apache.poi.ss.usermodel.*; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.stream.Collectors; /** * @author meiwei666 * @version 4.0 */ -public class ExcelToJsonUtils { +public class ExcelReaderUtils { public static void excelConvertJson(String inputDir, String outputDir) throws IOException { var listFiles = FileUtils.getAllReadableFiles(new File(inputDir)) @@ -54,7 +48,7 @@ public class ExcelToJsonUtils { var outputFilePath = FileUtils.joinPath(outputDir, jsonFileName); FileUtils.deleteFile(new File(outputFilePath)); - FileUtils.writeStringToFile(new File(outputFilePath), JsonUtils.object2StringPrettyPrinter(resourceData), true); + FileUtils.writeStringToFile(new File(outputFilePath), JsonUtils.object2String(resourceData), true); } } @@ -63,16 +57,17 @@ public class ExcelToJsonUtils { var wb = createWorkbook(inputStream, fileName); // 默认取到第一个sheet页 var sheet = wb.getSheetAt(0); + var iterator = sheet.iterator(); //设置所有列 - var headers = getHeaders(sheet, fileName); + var headers = getHeaders(iterator, fileName); // 行数定位到有效数据行,默认是第四行为有效数据行 - var iterator = sheet.iterator(); - iterator.next(); - iterator.next(); - iterator.next(); +// var iterator = sheet.iterator(); +// iterator.next(); +// iterator.next(); +// iterator.next(); // 从ROW_SERVER这行开始读取数据 - List rows = new ArrayList<>(); + List> rows = new ArrayList<>(); while (iterator.hasNext()) { var row = iterator.next(); @@ -87,14 +82,14 @@ public class ExcelToJsonUtils { var content = CellUtils.getCellStringValue(cell); columns.add(content); } - rows.add(ResourceRow.valueOf(row.getRowNum() + 1, columns)); + rows.add(columns); } return ResourceData.valueOf(fileName, headers, rows); } // 只读取代码里写的字段 - private static List getHeaders(Sheet sheet, String fileName) { - var iterator = sheet.iterator(); + private static List getHeaders(Iterator iterator, String fileName) { +// var iterator = sheet.iterator(); // 获取配置表的有效列名称,默认第一行就是字段名称 var fieldRow = iterator.next(); if (fieldRow == null) { @@ -105,7 +100,7 @@ public class ExcelToJsonUtils { if (typeRow == null) { throw new RunException("无法获取资源[class:{}]的Excel文件的类型控制列", fileName); } - + var desRow = iterator.next(); var headerList = new ArrayList(); var cellFieldMap = new HashMap(); for (var i = 0; i < fieldRow.getLastCellNum(); i++) { diff --git a/storage/src/test/java/com/zfoo/storage/ApplicationTest.java b/storage/src/test/java/com/zfoo/storage/ApplicationTest.java index 4250cdcf..c7ac921b 100644 --- a/storage/src/test/java/com/zfoo/storage/ApplicationTest.java +++ b/storage/src/test/java/com/zfoo/storage/ApplicationTest.java @@ -47,6 +47,7 @@ public class ApplicationTest { var studentManager = context.getBean(StudentManager.class); var studentResources = studentManager.studentResources; + var studentCsvResources = studentManager.studentCsvResources; // 类名称和Excel名称必须完全一致,Excel的列名称必须对应对象的属性名称 // 类名称和Excel名称必须完全一致,Excel的列名称必须对应对象的属性名称 for (StudentResource resource : studentResources.getAll()) { @@ -64,6 +65,10 @@ public class ApplicationTest { var valuesByIndex = studentResources.getIndex("name", "james0"); logger.info(JsonUtils.object2String(valuesByIndex)); + // 通过索引找对应的行 + var csvValuesByIndex = studentCsvResources.getIndex("name", "james0"); + logger.info(JsonUtils.object2String(csvValuesByIndex)); + // Excel的映射内容需要在被Spring管理的bean的方法上加上@ResInjection注解,即可自动注入Excel对应的对象 var testManager = context.getBean(TestManager.class); var testResources = testManager.testResources; diff --git a/storage/src/test/java/com/zfoo/storage/StudentManager.java b/storage/src/test/java/com/zfoo/storage/StudentManager.java index 06113f8b..ef07e04d 100644 --- a/storage/src/test/java/com/zfoo/storage/StudentManager.java +++ b/storage/src/test/java/com/zfoo/storage/StudentManager.java @@ -15,6 +15,7 @@ package com.zfoo.storage; import com.zfoo.storage.model.anno.ResInjection; import com.zfoo.storage.model.vo.Storage; +import com.zfoo.storage.resource.StudentCsvResource; import com.zfoo.storage.resource.StudentResource; import org.springframework.stereotype.Component; @@ -27,5 +28,7 @@ public class StudentManager { @ResInjection public Storage studentResources; + @ResInjection + public Storage studentCsvResources; } diff --git a/storage/src/test/java/com/zfoo/storage/excel/ExcelTest.java b/storage/src/test/java/com/zfoo/storage/excel/ExcelTest.java index 46d84771..26780eba 100644 --- a/storage/src/test/java/com/zfoo/storage/excel/ExcelTest.java +++ b/storage/src/test/java/com/zfoo/storage/excel/ExcelTest.java @@ -13,7 +13,7 @@ package com.zfoo.storage.excel; -import com.zfoo.storage.util.ExcelToJsonUtils; +import com.zfoo.storage.util.ExcelReaderUtils; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermodel.Workbook; @@ -37,7 +37,7 @@ public class ExcelTest { public void excelConvertJson() throws Exception{ String inputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel"; String outputDir = "E:\\workspace\\zfoo\\storage\\src\\test\\resources\\excel"; - ExcelToJsonUtils.excelConvertJson(inputDir, outputDir); + ExcelReaderUtils.excelConvertJson(inputDir, outputDir); } @Test diff --git a/storage/src/test/java/com/zfoo/storage/resource/StudentCsvResource.java b/storage/src/test/java/com/zfoo/storage/resource/StudentCsvResource.java new file mode 100644 index 00000000..eac5d698 --- /dev/null +++ b/storage/src/test/java/com/zfoo/storage/resource/StudentCsvResource.java @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2020 The zfoo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed + * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and limitations under the License. + */ + +package com.zfoo.storage.resource; + +import com.zfoo.storage.model.anno.Id; +import com.zfoo.storage.model.anno.Index; +import com.zfoo.storage.model.anno.Resource; + +/** + * @author godotg + * @version 4.0 + */ +@Resource +public class StudentCsvResource { + + @Id + private int id; + + /** + * 索引,默认为可重复的索引 + */ + @Index + private String name; + + private int age; + private float score; + private String[] courses; + private User[] users; + private User user; + + /** + * 不想映射的字段必须加上transient关键字,这样就不会从Excel中去找对应的列 + */ + private transient String notMapContent; + + public int getId() { + return id; + } + + public String getName() { + return name; + } + + public int getAge() { + return age; + } + + public float getScore() { + return score; + } + + public String[] getCourses() { + return courses; + } + + public User[] getUsers() { + return users; + } + + public User getUser() { + return user; + } + + public String getNotMapContent() { + return notMapContent; + } +} diff --git a/storage/src/test/resources/StudentResource.xlsx b/storage/src/test/resources/StudentResource.xlsx deleted file mode 100644 index d7378b7a60000be9ed5a13782afd0f5c7adfa986..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 10035 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 W72qH~2mqi!el!p_zW7NW!2ba{XC@B- diff --git a/storage/src/test/resources/excel/StudentCsvResource.csv b/storage/src/test/resources/excel/StudentCsvResource.csv new file mode 100644 index 00000000..116b2e8e --- /dev/null +++ b/storage/src/test/resources/excel/StudentCsvResource.csv @@ -0,0 +1,7 @@ +id,name,age,score,courses,users,user +string,string,int,float,array,array,string +des,des,des,des,des,des,des +1000,james0,10,60.8,"[""History"",""Chiness""]","[{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22},{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}]","{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}" +1001,james1,10,70.1,"[""History"",""Chiness""]","[{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22},{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":23}]","{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}" +1002,james2,10,80.2,"[""History"",""Chiness""]","[{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22},{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":24}]","{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}" +1003,james3,10,59,"[""History"",""Chiness""]","[{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22},{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":25}]","{""id"":""1000"",""name"":""SunInsanity"",""sex"":""boy"",""age"":22}"