Browse Source

fix sax read

Looly 6 years ago
parent
commit
3d8e01fe56

+ 54 - 25
hutool-db/src/main/java/cn/hutool/db/PageResult.java

@@ -6,66 +6,87 @@ import cn.hutool.core.util.PageUtil;
 
 /**
  * 分页数据结果集
- * @author Looly
  *
  * @param <T> 结果集项的类型
+ * @author Looly
  */
-public class PageResult<T> extends ArrayList<T>{
+public class PageResult<T> extends ArrayList<T> {
 	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<T> extends ArrayList<T>{
 	public int getNumPerPage() {
 		return pageSize;
 	}
+
 	/**
 	 * 设置每页结果数
+	 *
 	 * @param pageSize 每页结果数
 	 * @deprecated 请使用 {@link #setPageSize(int)}
 	 */
@@ -83,57 +106,63 @@ public class PageResult<T> extends ArrayList<T>{
 	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 是否最后一页
 	 */

+ 98 - 86
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读取<br>
  * 参考:http://www.cnblogs.com/wshsdlau/p/5643862.html
- * 
- * @author looly
  *
+ * @author looly
  */
 public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> 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<BoundSheetRecord> boundSheetRecords = new ArrayList<>();
 
 	private boolean isOutputNextStringRecord;
@@ -64,7 +74,9 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
 	// 存储行记录的容器
 	private List<Object> 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<Excel03SaxReader> i
 
 	/**
 	 * 构造
-	 * 
+	 *
 	 * @param rowHandler 行处理器
 	 */
 	public Excel03SaxReader(RowHandler rowHandler) {
@@ -101,8 +113,8 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> 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<Excel03SaxReader> i
 
 	/**
 	 * 获得Sheet序号,如果处理所有sheet,获得最大的Sheet序号,从0开始
-	 * 
+	 *
 	 * @return sheet序号
 	 */
 	public int getSheetIndex() {
@@ -141,7 +153,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
 
 	/**
 	 * 获得Sheet名,如果处理所有sheet,获得后一个Sheet名,从0开始
-	 * 
+	 *
 	 * @return Sheet名
 	 */
 	public String getSheetName() {
@@ -153,7 +165,7 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
 
 	/**
 	 * HSSFListener 监听方法,处理 Record
-	 * 
+	 *
 	 * @param record 记录
 	 */
 	@Override
@@ -195,92 +207,92 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> 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;
+			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 = formatListener.formatNumberDateCell(frec);
+					value = StrUtil.wrap(HSSFFormulaParser.toFormulaString(stubWorkbook, formulaRec.getParsedExpression()), "\"");
 				}
-			} 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(formulaRec.getColumn(), value);
+				break;
+			case StringRecord.sid:
+				// 单元格中公式的字符串
+				if (isOutputNextStringRecord) {
+					// String for formula
+					// value = ((StringRecord) record).getString();
+					isOutputNextStringRecord = false;
 				}
-			}
-
-			// 向容器加入列值
-			rowCellList.add(numrec.getColumn(), value);
-			break;
-		default:
-			break;
+				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<Excel03SaxReader> i
 
 	/**
 	 * 是否处理当前sheet
-	 * 
+	 *
 	 * @return 是否处理当前sheet
 	 */
 	private boolean isProcessCurrentSheet() {

+ 50 - 39
hutool-poi/src/main/java/cn/hutool/poi/excel/sax/Excel07SaxReader.java

@@ -31,24 +31,33 @@ import cn.hutool.poi.exceptions.POIException;
 /**
  * Sax方式读取Excel文件<br>
  * Excel2007格式说明见:http://www.cnblogs.com/wangmingshun/p/6654143.html
- * 
+ *
  * @author Looly
  * @since 3.1.2
- *
  */
 public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> i
 	// 存储每行的列元素
 	List<Object> rowCellList = new ArrayList<>();
 
-	/** 行处理器 */
+	/**
+	 * 行处理器
+	 */
 	private RowHandler rowHandler;
 
 	/**
 	 * 构造
-	 * 
+	 *
 	 * @param rowHandler 行处理器
 	 */
 	public Excel07SaxReader(RowHandler rowHandler) {
@@ -97,7 +106,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
 
 	/**
 	 * 设置行处理器
-	 * 
+	 *
 	 * @param rowHandler 行处理器
 	 * @return this
 	 */
@@ -129,9 +138,9 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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<Excel07SaxReader> 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) {