From 3d8e01fe56769eef41264a54104e0551738e5c81 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 27 Sep 2019 21:12:30 +0800 Subject: [PATCH] fix sax read --- .../main/java/cn/hutool/db/PageResult.java | 79 +++++--- .../poi/excel/sax/Excel03SaxReader.java | 190 ++++++++++-------- .../poi/excel/sax/Excel07SaxReader.java | 89 ++++---- 3 files changed, 205 insertions(+), 153 deletions(-) diff --git a/hutool-db/src/main/java/cn/hutool/db/PageResult.java b/hutool-db/src/main/java/cn/hutool/db/PageResult.java index 0ec4f303d..0cacc7eba 100644 --- a/hutool-db/src/main/java/cn/hutool/db/PageResult.java +++ b/hutool-db/src/main/java/cn/hutool/db/PageResult.java @@ -6,66 +6,87 @@ import cn.hutool.core.util.PageUtil; /** * 分页数据结果集 - * @author Looly * * @param 结果集项的类型 + * @author Looly */ -public class PageResult extends ArrayList{ +public class PageResult extends ArrayList { private static final long serialVersionUID = 9056411043515781783L; - + public static final int DEFAULT_PAGE_SIZE = Page.DEFAULT_PAGE_SIZE; - - /** 页码 */ + + /** + * 页码 + */ private int page; - /** 每页结果数 */ + /** + * 每页结果数 + */ private int pageSize; - /** 总页数 */ + /** + * 总页数 + */ private int totalPage; - /** 总数 */ + /** + * 总数 + */ private int total; - + //---------------------------------------------------------- Constructor start + /** * 构造 - * @param page 页码 + */ + public PageResult() { + this(0, DEFAULT_PAGE_SIZE); + } + + /** + * 构造 + * + * @param page 页码 * @param pageSize 每页结果数 */ public PageResult(int page, int pageSize) { super(pageSize <= 0 ? DEFAULT_PAGE_SIZE : pageSize); - - this.page = page <= 0 ? 0 : page; + + this.page = Math.max(page, 0); this.pageSize = pageSize <= 0 ? DEFAULT_PAGE_SIZE : pageSize; } - + /** * 构造 - * @param page 页码 + * + * @param page 页码 * @param pageSize 每页结果数 - * @param total 结果总数 + * @param total 结果总数 */ public PageResult(int page, int pageSize, int total) { this(page, pageSize); - + this.total = total; - this.totalPage = PageUtil.totalPage(total,pageSize); + this.totalPage = PageUtil.totalPage(total, pageSize); } //---------------------------------------------------------- Constructor end - + //---------------------------------------------------------- Getters and Setters start + /** * @return 页码 */ public int getPage() { return page; } + /** * 设置页码 + * * @param page 页码 */ public void setPage(int page) { this.page = page; } - + /** * @return 每页结果数 * @deprecated 请使用{@link #getPageSize()} @@ -74,8 +95,10 @@ public class PageResult extends ArrayList{ public int getNumPerPage() { return pageSize; } + /** * 设置每页结果数 + * * @param pageSize 每页结果数 * @deprecated 请使用 {@link #setPageSize(int)} */ @@ -83,57 +106,63 @@ public class PageResult extends ArrayList{ public void setNumPerPage(int pageSize) { this.pageSize = pageSize; } - + /** * @return 每页结果数 */ public int getPageSize() { return pageSize; } + /** * 设置每页结果数 + * * @param pageSize 每页结果数 */ public void setPageSize(int pageSize) { this.pageSize = pageSize; } - + /** * @return 总页数 */ public int getTotalPage() { return totalPage; } + /** * 设置总页数 + * * @param totalPage 总页数 */ public void setTotalPage(int totalPage) { this.totalPage = totalPage; } - + /** * @return 总数 */ public int getTotal() { return total; } + /** * 设置总数 + * * @param total 总数 */ public void setTotal(int total) { this.total = total; } //---------------------------------------------------------- Getters and Setters end - + /** * @return 是否第一页 */ - public boolean isFirst(){ + public boolean isFirst() { return this.page == 0; } - + /** * @return 是否最后一页 */ diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java index f7fa973aa..6dbb29fe4 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel03SaxReader.java @@ -6,6 +6,7 @@ import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import cn.hutool.core.util.ObjectUtil; import org.apache.poi.hssf.eventusermodel.EventWorkbookBuilder.SheetRecordCollectingListener; import org.apache.poi.hssf.eventusermodel.FormatTrackingHSSFListener; import org.apache.poi.hssf.eventusermodel.HSSFEventFactory; @@ -37,26 +38,35 @@ import cn.hutool.poi.exceptions.POIException; /** * Excel2003格式的事件-用户模型方式读取器,在Hutool中,统一将此归类为Sax读取
* 参考:http://www.cnblogs.com/wshsdlau/p/5643862.html - * - * @author looly * + * @author looly */ public class Excel03SaxReader extends AbstractExcelSaxReader implements HSSFListener { - /** 如果为公式,true表示输出公式计算后的结果值,false表示输出公式本身 */ + /** + * 如果为公式,true表示输出公式计算后的结果值,false表示输出公式本身 + */ private boolean isOutputFormulaValues = true; - /** 用于解析公式 */ + /** + * 用于解析公式 + */ private SheetRecordCollectingListener workbookBuildingListener; - /** 子工作簿,用于公式计算 */ + /** + * 子工作簿,用于公式计算 + */ private HSSFWorkbook stubWorkbook; - /** 静态字符串表 */ + /** + * 静态字符串表 + */ private SSTRecord sstRecord; private FormatTrackingHSSFListener formatListener; - /** Sheet边界记录,此Record中可以获得Sheet名 */ + /** + * Sheet边界记录,此Record中可以获得Sheet名 + */ private List boundSheetRecords = new ArrayList<>(); private boolean isOutputNextStringRecord; @@ -64,7 +74,9 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i // 存储行记录的容器 private List rowCellList = new ArrayList<>(); - /** 自定义需要处理的sheet编号,如果-1表示处理所有sheet */ + /** + * 自定义需要处理的sheet编号,如果-1表示处理所有sheet + */ private int rid = -1; // 当前表索引 private int curRid = -1; @@ -73,7 +85,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i /** * 构造 - * + * * @param rowHandler 行处理器 */ public Excel03SaxReader(RowHandler rowHandler) { @@ -101,8 +113,8 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i /** * 读取 - * - * @param fs {@link POIFSFileSystem} + * + * @param fs {@link POIFSFileSystem} * @param rid sheet序号 * @return this * @throws POIException IO异常包装 @@ -132,7 +144,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i /** * 获得Sheet序号,如果处理所有sheet,获得最大的Sheet序号,从0开始 - * + * * @return sheet序号 */ public int getSheetIndex() { @@ -141,7 +153,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i /** * 获得Sheet名,如果处理所有sheet,获得后一个Sheet名,从0开始 - * + * * @return Sheet名 */ public String getSheetName() { @@ -153,7 +165,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i /** * HSSFListener 监听方法,处理 Record - * + * * @param record 记录 */ @Override @@ -195,92 +207,92 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i } // ---------------------------------------------------------------------------------------------- Private method start + /** * 处理单元格值 - * + * * @param record 单元格 */ private void processCellValue(Record record) { Object value = null; - - switch (record.getSid()) { - case BlankRecord.sid: - // 空白记录 - BlankRecord brec = (BlankRecord) record; - rowCellList.add(brec.getColumn(), StrUtil.EMPTY); - break; - case BoolErrRecord.sid: // 布尔类型 - BoolErrRecord berec = (BoolErrRecord) record; - rowCellList.add(berec.getColumn(), berec.getBooleanValue()); - break; - case FormulaRecord.sid: // 公式类型 - FormulaRecord frec = (FormulaRecord) record; - if (isOutputFormulaValues) { - if (Double.isNaN(frec.getValue())) { - // Formula result is a string - // This is stored in the next record - isOutputNextStringRecord = true; - } else { - value = formatListener.formatNumberDateCell(frec); - } - } else { - value = '"' + HSSFFormulaParser.toFormulaString(stubWorkbook, frec.getParsedExpression()) + '"'; - } - rowCellList.add(frec.getColumn(), value); - break; - case StringRecord.sid:// 单元格中公式的字符串 - if (isOutputNextStringRecord) { - // String for formula - StringRecord srec = (StringRecord) record; - value = srec.getString(); - isOutputNextStringRecord = false; - } - break; - case LabelRecord.sid: - LabelRecord lrec = (LabelRecord) record; - this.rowCellList.add(lrec.getColumn(), value); - break; - case LabelSSTRecord.sid: // 字符串类型 - LabelSSTRecord lsrec = (LabelSSTRecord) record; - if (sstRecord == null) { - rowCellList.add(lsrec.getColumn(), StrUtil.EMPTY); - } else { - value = sstRecord.getString(lsrec.getSSTIndex()).toString(); - rowCellList.add(lsrec.getColumn(), value); - } - break; - case NumberRecord.sid: // 数字类型 - NumberRecord numrec = (NumberRecord) record; - - final String formatString = formatListener.getFormatString(numrec); - if(formatString.contains(StrUtil.DOT)) { - //浮点数 - value = numrec.getValue(); - }else if(formatString.contains(StrUtil.SLASH) || formatString.contains(StrUtil.COLON)) { - //日期 - value = formatListener.formatNumberDateCell(numrec); - }else { - double numValue = numrec.getValue(); - final long longPart = (long) numValue; - // 对于无小数部分的数字类型,转为Long,否则保留原数字 - if(longPart == numValue) { - value = longPart; - }else { - value = numValue; - } - } - // 向容器加入列值 - rowCellList.add(numrec.getColumn(), value); - break; - default: - break; + switch (record.getSid()) { + case BlankRecord.sid: + // 空白记录 + rowCellList.add(((BlankRecord) record).getColumn(), StrUtil.EMPTY); + break; + case BoolErrRecord.sid: + // 布尔类型 + final BoolErrRecord berec = (BoolErrRecord) record; + rowCellList.add(berec.getColumn(), berec.getBooleanValue()); + break; + case FormulaRecord.sid: + // 公式类型 + FormulaRecord formulaRec = (FormulaRecord) record; + if (isOutputFormulaValues) { + if (Double.isNaN(formulaRec.getValue())) { + // Formula result is a string + // This is stored in the next record + isOutputNextStringRecord = true; + } else { + value = formatListener.formatNumberDateCell(formulaRec); + } + } else { + value = StrUtil.wrap(HSSFFormulaParser.toFormulaString(stubWorkbook, formulaRec.getParsedExpression()), "\""); + } + rowCellList.add(formulaRec.getColumn(), value); + break; + case StringRecord.sid: + // 单元格中公式的字符串 + if (isOutputNextStringRecord) { + // String for formula + // value = ((StringRecord) record).getString(); + isOutputNextStringRecord = false; + } + break; + case LabelRecord.sid: + final LabelRecord lrec = (LabelRecord) record; + value = lrec.getValue(); + this.rowCellList.add(lrec.getColumn(), value); + break; + case LabelSSTRecord.sid: + // 字符串类型 + LabelSSTRecord lsrec = (LabelSSTRecord) record; + if (null != sstRecord) { + value = sstRecord.getString(lsrec.getSSTIndex()).toString(); + } + rowCellList.add(lsrec.getColumn(), ObjectUtil.defaultIfNull(value, StrUtil.EMPTY)); + break; + case NumberRecord.sid: // 数字类型 + final NumberRecord numrec = (NumberRecord) record; + final String formatString = formatListener.getFormatString(numrec); + if (formatString.contains(StrUtil.DOT)) { + //浮点数 + value = numrec.getValue(); + } else if (formatString.contains(StrUtil.SLASH) || formatString.contains(StrUtil.COLON)) { + //日期 + value = formatListener.formatNumberDateCell(numrec); + } else { + final double doubleValue = numrec.getValue(); + final long longPart = (long) doubleValue; + // 对于无小数部分的数字类型,转为Long,否则保留原数字 + if (((double) longPart) == doubleValue) { + value = longPart; + } else { + value = doubleValue; + } + } + // 向容器加入列值 + rowCellList.add(numrec.getColumn(), value); + break; + default: + break; } } /** * 处理行结束后的操作,{@link LastCellOfRowDummyRecord}是行结束的标识Record - * + * * @param lastCell 行结束的标识Record */ private void processLastCell(LastCellOfRowDummyRecord lastCell) { @@ -292,7 +304,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i /** * 是否处理当前sheet - * + * * @return 是否处理当前sheet */ private boolean isProcessCurrentSheet() { diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java index f61b3a6a1..a578ee2af 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java @@ -31,24 +31,33 @@ import cn.hutool.poi.exceptions.POIException; /** * Sax方式读取Excel文件
* Excel2007格式说明见:http://www.cnblogs.com/wangmingshun/p/6654143.html - * + * * @author Looly * @since 3.1.2 - * */ public class Excel07SaxReader extends AbstractExcelSaxReader implements ContentHandler { // saxParser private static final String CLASS_SAXPARSER = "org.apache.xerces.parsers.SAXParser"; - /** Cell单元格元素 */ + /** + * Cell单元格元素 + */ private static final String C_ELEMENT = "c"; - /** 行元素 */ + /** + * 行元素 + */ private static final String ROW_ELEMENT = "row"; - /** Cell中的行列号 */ + /** + * Cell中的行列号 + */ private static final String R_ATTR = "r"; - /** Cell类型 */ + /** + * Cell类型 + */ private static final String T_ELEMENT = "t"; - /** SST(SharedStringsTable) 的索引 */ + /** + * SST(SharedStringsTable) 的索引 + */ private static final String S_ATTR_VALUE = "s"; // 列中属性值 private static final String T_ATTR_VALUE = "t"; @@ -73,9 +82,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i private String maxCellCoordinate; // 单元格的格式表,对应style.xml private StylesTable stylesTable; - // 单元格存储格式的索引,对应style.xml中的numFmts元素的子元素索引 - private int numFmtIndex; - // 单元格存储的格式化字符串,nmtFmt的formateCode属性的值 + // 单元格存储的格式化字符串,nmtFmt的formatCode属性的值 private String numFmtString; // sheet的索引 private int sheetIndex; @@ -83,12 +90,14 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i // 存储每行的列元素 List rowCellList = new ArrayList<>(); - /** 行处理器 */ + /** + * 行处理器 + */ private RowHandler rowHandler; /** * 构造 - * + * * @param rowHandler 行处理器 */ public Excel07SaxReader(RowHandler rowHandler) { @@ -97,7 +106,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i /** * 设置行处理器 - * + * * @param rowHandler 行处理器 * @return this */ @@ -129,9 +138,9 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i /** * 开始读取Excel,Sheet编号从0开始计数 - * + * * @param opcPackage {@link OPCPackage},Excel包 - * @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet + * @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 */ @@ -178,7 +187,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i * 读到一个xml开始标签时的回调处理方法 */ @Override - public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { + public void startElement(String uri, String localName, String qName, Attributes attributes) { // 单元格元素 if (C_ELEMENT.equals(qName)) { @@ -203,11 +212,12 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i /** * 设置单元格的类型 * - * @param attribute + * @param attribute 属性 */ private void setCellType(Attributes attribute) { - // 重置numFmtIndex,numFmtString的值 - numFmtIndex = 0; + // 单元格存储格式的索引,对应style.xml中的numFmts元素的子元素索引 + int numFmtIndex; + // numFmtString的值 numFmtString = ""; this.cellDataType = CellDataType.of(attribute.getValue(T_ATTR_VALUE)); @@ -232,13 +242,14 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i * 标签结束的回调处理方法 */ @Override - public void endElement(String uri, String localName, String qName) throws SAXException { + public void endElement(String uri, String localName, String qName) { final String contentStr = StrUtil.trim(lastContent); - if (T_ELEMENT.equals(qName)) { - // type标签 - // rowCellList.add(curCell++, contentStr); - } else if (C_ELEMENT.equals(qName)) { +// if (T_ELEMENT.equals(qName)) { +// // type标签 +// // rowCellList.add(curCell++, contentStr); +// } else + if (C_ELEMENT.equals(qName)) { // cell标签 Object value = ExcelSaxUtil.getDataValue(this.cellDataType, contentStr, this.sharedStringsTable, this.numFmtString); // 补全单元格之间的空格 @@ -259,8 +270,8 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i rowHandler.handle(sheetIndex, curRow, rowCellList); // 一行结束 - // 清空rowCellList, - rowCellList.clear(); + // 新建一个新列,之前的列抛弃(可能被回收或rowHandler处理) + rowCellList = new ArrayList<>(curCell + 1); // 行数增加 curRow++; // 当前列置0 @@ -275,7 +286,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i * s标签结束的回调处理方法 */ @Override - public void characters(char[] ch, int start, int length) throws SAXException { + public void characters(char[] ch, int start, int length) { // 得到单元格内容的值 lastContent = lastContent.concat(new String(ch, start, length)); } @@ -290,47 +301,48 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i * ?xml标签的回调处理方法 */ @Override - public void startDocument() throws SAXException { + public void startDocument() { // pass } @Override - public void endDocument() throws SAXException { + public void endDocument() { // pass } @Override - public void startPrefixMapping(String prefix, String uri) throws SAXException { + public void startPrefixMapping(String prefix, String uri) { // pass } @Override - public void endPrefixMapping(String prefix) throws SAXException { + public void endPrefixMapping(String prefix) { // pass } @Override - public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException { + public void ignorableWhitespace(char[] ch, int start, int length) { // pass } @Override - public void processingInstruction(String target, String data) throws SAXException { + public void processingInstruction(String target, String data) { // pass } @Override - public void skippedEntity(String name) throws SAXException { + public void skippedEntity(String name) { // pass } // --------------------------------------------------------------------------------------- Pass method end // --------------------------------------------------------------------------------------- Private method start + /** * 处理流中的Excel数据 - * + * * @param sheetInputStream sheet流 - * @throws IOException IO异常 + * @throws IOException IO异常 * @throws SAXException SAX异常 */ private void parse(InputStream sheetInputStream) throws IOException, SAXException { @@ -342,7 +354,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i * * @param preCoordinate 前一个单元格坐标 * @param curCoordinate 当前单元格坐标 - * @param isEnd 是否为最后一个单元格 + * @param isEnd 是否为最后一个单元格 */ private void fillBlankCell(String preCoordinate, String curCoordinate, boolean isEnd) { if (false == curCoordinate.equals(preCoordinate)) { @@ -359,12 +371,11 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i /** * 获取sheet的解析器 * - * @param sharedStringsTable * @return {@link XMLReader} * @throws SAXException SAX异常 */ private XMLReader fetchSheetReader() throws SAXException { - XMLReader xmlReader = null; + XMLReader xmlReader; try { xmlReader = XMLReaderFactory.createXMLReader(CLASS_SAXPARSER); } catch (SAXException e) {