From 60efd24469f5178cba4f9d0c9f55e787f45542b2 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 00:49:24 +0800 Subject: [PATCH 01/28] add sheetId support --- CHANGELOG.md | 1 + .../cn/hutool/poi/excel/ExcelFileUtil.java | 24 +- .../java/cn/hutool/poi/excel/ExcelUtil.java | 19 +- .../poi/excel/sax/AbstractExcelSaxReader.java | 38 ---- .../poi/excel/sax/Excel03SaxReader.java | 16 +- .../poi/excel/sax/Excel07SaxReader.java | 210 ++++++++++-------- .../hutool/poi/excel/sax/ExcelSaxReader.java | 74 ++++-- .../cn/hutool/poi/excel/sax/ExcelSaxUtil.java | 5 +- .../hutool/poi/excel/sax/SheetRidReader.java | 110 +++++++++ 9 files changed, 324 insertions(+), 173 deletions(-) delete mode 100644 hutool-poi/src/main/java/cn/hutool/poi/excel/sax/AbstractExcelSaxReader.java create mode 100644 hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 47b464ed7..6a4932d02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ * 【core 】 NumberUtil.factorial注释明确(pr#1126@Github) * 【core 】 NumberUtil增加isPowerOfTwo方法(pr#1132@Github) * 【core 】 优化BooleanUtil的校验逻辑(pr#1137@Github) +* 【poi 】 改进sax方式读取逻辑,支持sheetId(issue#1141@Github) ### Bug修复 * 【crypto 】 修复SM2验签后无法解密问题(issue#I1W0VP@Gitee) diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelFileUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelFileUtil.java index 2c04fc90e..73e686160 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelFileUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelFileUtil.java @@ -1,9 +1,10 @@ package cn.hutool.poi.excel; import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; import org.apache.poi.poifs.filesystem.FileMagic; -import java.io.BufferedInputStream; +import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -48,11 +49,24 @@ public class ExcelFileUtil { * @return 是否为XLSX格式的Excel文件(XSSF) */ public static boolean isXlsx(InputStream in) { - if (false == in.markSupported()) { - in = new BufferedInputStream(in); - } try { - return FileMagic.valueOf(in) == FileMagic.OOXML; + return FileMagic.valueOf(IoUtil.toMarkSupportStream(in)) == FileMagic.OOXML; + } catch (IOException e) { + throw new IORuntimeException(e); + } + } + + /** + * 是否为XLSX格式的Excel文件(XSSF)
+ * XLSX文件主要用于Excel 2007+创建 + * + * @param file excel文件 + * @return 是否为XLSX格式的Excel文件(XSSF) + * @since 5.4.4 + */ + public static boolean isXlsx(File file) { + try { + return FileMagic.valueOf(file) == FileMagic.OOXML; } catch (IOException e) { throw new IORuntimeException(e); } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java index 1fd7a470b..cfcc01a3f 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java @@ -12,7 +12,6 @@ import cn.hutool.poi.excel.sax.Excel03SaxReader; import cn.hutool.poi.excel.sax.Excel07SaxReader; import cn.hutool.poi.excel.sax.handler.RowHandler; -import java.io.BufferedInputStream; import java.io.File; import java.io.InputStream; @@ -34,13 +33,7 @@ public class ExcelUtil { * @since 3.2.0 */ public static void readBySax(String path, int sheetIndex, RowHandler rowHandler) { - BufferedInputStream in = null; - try { - in = FileUtil.getInputStream(path); - readBySax(in, sheetIndex, rowHandler); - } finally { - IoUtil.close(in); - } + readBySax(FileUtil.file(path), sheetIndex, rowHandler); } /** @@ -52,12 +45,10 @@ public class ExcelUtil { * @since 3.2.0 */ public static void readBySax(File file, int sheetIndex, RowHandler rowHandler) { - BufferedInputStream in = null; - try { - in = FileUtil.getInputStream(file); - readBySax(in, sheetIndex, rowHandler); - } finally { - IoUtil.close(in); + if (ExcelFileUtil.isXlsx(file)) { + read07BySax(file, sheetIndex, rowHandler); + } else { + read03BySax(file, sheetIndex, rowHandler); } } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/AbstractExcelSaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/AbstractExcelSaxReader.java deleted file mode 100644 index ed3a245fe..000000000 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/AbstractExcelSaxReader.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.hutool.poi.excel.sax; - -import java.io.File; -import java.io.InputStream; - -import cn.hutool.core.io.FileUtil; -import cn.hutool.poi.exceptions.POIException; - -/** - * 抽象的Sax方式Excel读取器,提供一些共用方法 - * - * @author looly - * - * @param 子对象类型,用于标记返回值this - * @since 3.2.0 - */ -public abstract class AbstractExcelSaxReader implements ExcelSaxReader { - - @Override - public T read(String path) throws POIException { - return read(FileUtil.file(path)); - } - - @Override - public T read(File file) throws POIException { - return read(file, -1); - } - - @Override - public T read(InputStream in) throws POIException { - return read(in, -1); - } - - @Override - public T read(String path, int sheetIndex) throws POIException { - return read(FileUtil.file(path), sheetIndex); - } -} 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 56beeef4a..6aa1e7bfd 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 @@ -30,7 +30,7 @@ import java.util.List; * * @author looly */ -public class Excel03SaxReader extends AbstractExcelSaxReader implements HSSFListener { +public class Excel03SaxReader implements HSSFListener, ExcelSaxReader { /** * 如果为公式,true表示输出公式计算后的结果值,false表示输出公式本身 @@ -83,18 +83,18 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i // ------------------------------------------------------------------------------ Read start @Override - public Excel03SaxReader read(File file, int rid) throws POIException { + public Excel03SaxReader read(File file, String idOrRid) throws POIException { try { - return read(new POIFSFileSystem(file), rid); + return read(new POIFSFileSystem(file), idOrRid); } catch (IOException e) { throw new POIException(e); } } @Override - public Excel03SaxReader read(InputStream excelStream, int rid) throws POIException { + public Excel03SaxReader read(InputStream excelStream, String idOrRid) throws POIException { try { - return read(new POIFSFileSystem(excelStream), rid); + return read(new POIFSFileSystem(excelStream), idOrRid); } catch (IOException e) { throw new POIException(e); } @@ -104,12 +104,12 @@ public class Excel03SaxReader extends AbstractExcelSaxReader i * 读取 * * @param fs {@link POIFSFileSystem} - * @param rid sheet序号 + * @param id sheet序号 * @return this * @throws POIException IO异常包装 */ - public Excel03SaxReader read(POIFSFileSystem fs, int rid) throws POIException { - this.rid = rid; + public Excel03SaxReader read(POIFSFileSystem fs, String id) throws POIException { + this.rid = Integer.parseInt(id); formatListener = new FormatTrackingHSSFListener(new MissingRecordAwareHSSFListener(this)); final HSSFRequest request = new HSSFRequest(); 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 0ff2aae60..d51ccc98c 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 @@ -1,10 +1,14 @@ package cn.hutool.poi.excel.sax; +import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IoUtil; import cn.hutool.core.text.StrBuilder; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.poi.excel.sax.handler.RowHandler; import cn.hutool.poi.exceptions.POIException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.ss.usermodel.BuiltinFormats; import org.apache.poi.xssf.eventusermodel.XSSFReader; @@ -12,10 +16,10 @@ import org.apache.poi.xssf.model.SharedStringsTable; import org.apache.poi.xssf.model.StylesTable; import org.apache.poi.xssf.usermodel.XSSFCellStyle; import org.xml.sax.Attributes; -import org.xml.sax.ContentHandler; -import org.xml.sax.Locator; +import org.xml.sax.helpers.DefaultHandler; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Iterator; @@ -28,7 +32,7 @@ import java.util.List; * @author Looly * @since 3.1.2 */ -public class Excel07SaxReader extends AbstractExcelSaxReader implements ContentHandler { +public class Excel07SaxReader extends DefaultHandler implements ExcelSaxReader { // sheet r:Id前缀 private static final String RID_PREFIX = "rId"; @@ -92,20 +96,30 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i // ------------------------------------------------------------------------------ Read start @Override public Excel07SaxReader read(File file, int rid) throws POIException { + return read(file, RID_PREFIX + rid); + } + + @Override + public Excel07SaxReader read(File file, String idOrRid) throws POIException { try { - return read(OPCPackage.open(file), rid); - } catch (Exception e) { + return read(OPCPackage.open(file), idOrRid); + } catch (InvalidFormatException e) { throw new POIException(e); } } @Override public Excel07SaxReader read(InputStream in, int rid) throws POIException { - try { - return read(OPCPackage.open(in), rid); - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { + return read(in, RID_PREFIX + rid); + } + + @Override + public Excel07SaxReader read(InputStream in, String idOrRid) throws POIException { + try (final OPCPackage opcPackage = OPCPackage.open(in)) { + return read(opcPackage, idOrRid); + } catch (IOException e) { + throw new IORuntimeException(e); + } catch (InvalidFormatException e) { throw new POIException(e); } } @@ -113,53 +127,60 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i /** * 开始读取Excel,Sheet编号从0开始计数 * - * @param opcPackage {@link OPCPackage},Excel包 + * @param opcPackage {@link OPCPackage},Excel包,读取后不关闭 * @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 */ public Excel07SaxReader read(OPCPackage opcPackage, int rid) throws POIException { - InputStream sheetInputStream = null; + return read(opcPackage, RID_PREFIX + rid); + } + + /** + * 开始读取Excel,Sheet编号从0开始计数 + * + * @param opcPackage {@link OPCPackage},Excel包,读取后不关闭 + * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @return this + * @throws POIException POI异常 + */ + public Excel07SaxReader read(OPCPackage opcPackage, String idOrRid) throws POIException { try { - final XSSFReader xssfReader = new XSSFReader(opcPackage); - - // 获取共享样式表 - try { - stylesTable = xssfReader.getStylesTable(); - } catch (Exception e) { - //ignore - } - // 获取共享字符串表 - this.sharedStringsTable = xssfReader.getSharedStringsTable(); - - if (rid > -1) { - this.sheetIndex = rid; - // 根据 rId# 或 rSheet# 查找sheet - sheetInputStream = xssfReader.getSheet(RID_PREFIX + (rid + 1)); - ExcelSaxUtil.readFrom(sheetInputStream, this); - rowHandler.doAfterAllAnalysed(); - } else { - this.sheetIndex = -1; - // 遍历所有sheet - final Iterator sheetInputStreams = xssfReader.getSheetsData(); - while (sheetInputStreams.hasNext()) { - // 重新读取一个sheet时行归零 - index = 0; - this.sheetIndex++; - sheetInputStream = sheetInputStreams.next(); - ExcelSaxUtil.readFrom(sheetInputStream, this); - rowHandler.doAfterAllAnalysed(); - } - } - } catch (RuntimeException e) { - throw e; - } catch (Exception e) { + return read(new XSSFReader(opcPackage), idOrRid); + } catch (OpenXML4JException e) { throw new POIException(e); - } finally { - IoUtil.close(sheetInputStream); - IoUtil.close(opcPackage); + } catch (IOException e) { + throw new IORuntimeException(e); } - return this; + } + + /** + * 开始读取Excel,Sheet编号从0开始计数 + * + * @param xssfReader {@link XSSFReader},Excel读取器 + * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @return this + * @throws POIException POI异常 + * @since 5.4.4 + */ + public Excel07SaxReader read(XSSFReader xssfReader, String idOrRid) throws POIException { + // 获取共享样式表 + try { + stylesTable = xssfReader.getStylesTable(); + } catch (Exception e) { + //ignore + } + + // 获取共享字符串表 + try { + this.sharedStringsTable = xssfReader.getSharedStringsTable(); + } catch (IOException e) { + throw new IORuntimeException(e); + } catch (InvalidFormatException e) { + throw new POIException(e); + } + + return readSheets(xssfReader, idOrRid); } // ------------------------------------------------------------------------------ Read end @@ -196,53 +217,57 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i lastContent.append(ch, start, length); } - // --------------------------------------------------------------------------------------- Pass method start - @Override - public void setDocumentLocator(Locator locator) { - // pass - } + // --------------------------------------------------------------------------------------- Private method start /** - * ?xml标签的回调处理方法 + * 开始读取Excel,Sheet编号从0开始计数 + * + * @param xssfReader {@link XSSFReader},Excel读取器 + * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId0,如果为-1处理所有编号的sheet + * @return this + * @throws POIException POI异常 + * @since 5.4.4 */ - @Override - public void startDocument() { - // pass + private Excel07SaxReader readSheets(XSSFReader xssfReader, String idOrRid) throws POIException { + // 将sheetId转换为rid + if (NumberUtil.isInteger(idOrRid)) { + final SheetRidReader ridReader = new SheetRidReader(); + final String rid = ridReader.read(xssfReader).getRidBySheetId(idOrRid); + if (StrUtil.isNotEmpty(rid)) { + idOrRid = rid; + } + } + this.sheetIndex = Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRid, RID_PREFIX)); + InputStream sheetInputStream = null; + try { + if (this.sheetIndex > -1) { + // 根据 rId# 或 rSheet# 查找sheet + sheetInputStream = xssfReader.getSheet(RID_PREFIX + (this.sheetIndex + 1)); + ExcelSaxUtil.readFrom(sheetInputStream, this); + rowHandler.doAfterAllAnalysed(); + } else { + this.sheetIndex = -1; + // 遍历所有sheet + final Iterator sheetInputStreams = xssfReader.getSheetsData(); + while (sheetInputStreams.hasNext()) { + // 重新读取一个sheet时行归零 + index = 0; + this.sheetIndex++; + sheetInputStream = sheetInputStreams.next(); + ExcelSaxUtil.readFrom(sheetInputStream, this); + rowHandler.doAfterAllAnalysed(); + } + } + } catch (RuntimeException e) { + throw e; + } catch (Exception e) { + throw new POIException(e); + } finally { + IoUtil.close(sheetInputStream); + } + return this; } - @Override - public void endDocument() { - // pass - } - - @Override - public void startPrefixMapping(String prefix, String uri) { - // pass - } - - @Override - public void endPrefixMapping(String prefix) { - // pass - } - - @Override - public void ignorableWhitespace(char[] ch, int start, int length) { - // pass - } - - @Override - public void processingInstruction(String target, String data) { - // pass - } - - @Override - public void skippedEntity(String name) { - // pass - } - // --------------------------------------------------------------------------------------- Pass method end - - // --------------------------------------------------------------------------------------- Private method start - /** * 行开始 * @@ -317,10 +342,11 @@ public class Excel07SaxReader extends AbstractExcelSaxReader i /** * 在一行中的指定列增加值 + * * @param index 位置 * @param value 值 */ - private void addCellValue(int index, Object value){ + private void addCellValue(int index, Object value) { this.rowCellList.add(index, value); this.rowHandler.handleCell(this.sheetIndex, this.rowNumber, index, value, this.xssfCellStyle); } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java index 58cbc330d..fff65028f 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxReader.java @@ -1,10 +1,11 @@ package cn.hutool.poi.excel.sax; +import cn.hutool.core.io.FileUtil; +import cn.hutool.poi.exceptions.POIException; + import java.io.File; import java.io.InputStream; -import cn.hutool.poi.exceptions.POIException; - /** * Sax方式读取Excel接口,提供一些共用方法 * @author looly @@ -13,60 +14,105 @@ import cn.hutool.poi.exceptions.POIException; * @since 3.2.0 */ public interface ExcelSaxReader { + + /** + * 开始读取Excel + * + * @param file Excel文件 + * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @return this + * @throws POIException POI异常 + */ + T read(File file, String idOrRid) throws POIException; + + /** + * 开始读取Excel,读取结束后并不关闭流 + * + * @param in Excel流 + * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @return this + * @throws POIException POI异常 + */ + T read(InputStream in, String idOrRid) throws POIException; + /** * 开始读取Excel,读取所有sheet - * + * * @param path Excel文件路径 * @return this * @throws POIException POI异常 */ - T read(String path) throws POIException; + default T read(String path) throws POIException { + return read(FileUtil.file(path)); + } /** * 开始读取Excel,读取所有sheet - * + * * @param file Excel文件 * @return this * @throws POIException POI异常 */ - T read(File file) throws POIException; + default T read(File file) throws POIException { + return read(file, -1); + } /** * 开始读取Excel,读取所有sheet,读取结束后并不关闭流 - * + * * @param in Excel包流 * @return this * @throws POIException POI异常 */ - T read(InputStream in) throws POIException; + default T read(InputStream in) throws POIException { + return read(in, -1); + } /** * 开始读取Excel - * + * * @param path 文件路径 * @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 */ - T read(String path, int rid) throws POIException; + default T read(String path, int rid) throws POIException { + return read(FileUtil.file(path), rid); + } /** * 开始读取Excel - * + * + * @param path 文件路径 + * @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet + * @return this + * @throws POIException POI异常 + */ + default T read(String path, String rid) throws POIException { + return read(FileUtil.file(path), rid); + } + + /** + * 开始读取Excel + * * @param file Excel文件 * @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 */ - T read(File file, int rid) throws POIException; + default T read(File file, int rid) throws POIException{ + return read(file, String.valueOf(rid)); + } /** * 开始读取Excel,读取结束后并不关闭流 - * + * * @param in Excel流 * @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet * @return this * @throws POIException POI异常 */ - T read(InputStream in, int rid) throws POIException; + default T read(InputStream in, int rid) throws POIException{ + return read(in, String.valueOf(rid)); + }; } diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java index b8acb25ce..52b13ca49 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java @@ -73,9 +73,9 @@ public class ExcelSaxUtil { } break; case NUMBER: - try{ + try { result = getNumberValue(value, numFmtString); - }catch (NumberFormatException e){ + } catch (NumberFormatException e) { result = value; } break; @@ -150,6 +150,7 @@ public class ExcelSaxUtil { public static void readFrom(InputStream xmlDocStream, ContentHandler handler) throws DependencyException, POIException, IORuntimeException { XMLReader xmlReader; try { +// xmlReader = XMLReaderFactory.createXMLReader(); //noinspection deprecation xmlReader = SAXHelper.newXMLReader(); } catch (SAXException | ParserConfigurationException e) { diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java new file mode 100644 index 000000000..7af3c4884 --- /dev/null +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java @@ -0,0 +1,110 @@ +package cn.hutool.poi.excel.sax; + +import cn.hutool.core.io.IORuntimeException; +import cn.hutool.core.io.IoUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.exceptions.POIException; +import org.apache.poi.openxml4j.exceptions.InvalidFormatException; +import org.apache.poi.xssf.eventusermodel.XSSFReader; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.DefaultHandler; + +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; +import java.util.Map; + +/** + * 在Sax方式读取Excel时,读取sheet标签中sheetId和rid的对应关系,类似于: + *
+ * <sheet name="Sheet6" sheetId="4" r:id="6"/>
+ * 
+ * + * 读取结果为: + * + *
+ *     {"4": "6"}
+ * 
+ * + * @author looly + * @since 5.4.4 + */ +public class SheetRidReader extends DefaultHandler { + + private final static String TAG_NAME = "sheet"; + private final static String RID_ATTR = "r:id"; + private final static String SHEET_ID_ATTR = "sheetId"; + private final static String NAME_ATTR = "name"; + + private final Map ID_RID_MAP = new HashMap<>(); + private final Map NAME_RID_MAP = new HashMap<>(); + + /** + * 读取Wordkbook的XML中sheet标签中sheetId和rid的对应关系 + * + * @param xssfReader XSSF读取器 + */ + public SheetRidReader read(XSSFReader xssfReader){ + InputStream workbookData = null; + try{ + workbookData = xssfReader.getWorkbookData(); + ExcelSaxUtil.readFrom(workbookData, this); + } catch (InvalidFormatException e) { + throw new POIException(e); + } catch (IOException e) { + throw new IORuntimeException(e); + } finally { + IoUtil.close(workbookData); + } + return this; + } + + /** + * 根据sheetId获取rid + * + * @param sheetId Sheet的ID + * @return rid + */ + public String getRidBySheetId(String sheetId){ + return ID_RID_MAP.get(sheetId); + } + + /** + * 根据sheet name获取rid + * + * @param sheetName Sheet的name + * @return rid + */ + public String getRidByName(String sheetName){ + return NAME_RID_MAP.get(sheetName); + } + + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) { + if(TAG_NAME.equalsIgnoreCase(localName)){ + final int length = attributes.getLength(); + String sheetId = null; + String rid = null; + String name = null; + for (int i = 0; i < length; i++) { + switch (attributes.getLocalName(i)){ + case SHEET_ID_ATTR: + sheetId = attributes.getValue(i); + break; + case RID_ATTR: + rid = attributes.getValue(i); + break; + case NAME_ATTR: + name = attributes.getValue(i); + break; + } + if(StrUtil.isNotEmpty(sheetId)){ + ID_RID_MAP.put(sheetId, rid); + } + if(StrUtil.isNotEmpty(name)){ + NAME_RID_MAP.put(name, rid); + } + } + } + } +} From 4c278dcccb0b71523f560bfa8f5e2919636ffe2d Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 01:16:04 +0800 Subject: [PATCH 02/28] fix code for poi --- .../java/cn/hutool/poi/excel/ExcelUtil.java | 102 +++++++++++++----- .../cn/hutool/poi/excel/sax/ExcelSaxUtil.java | 15 +++ .../poi/excel/test/ExcelSaxReadTest.java | 10 +- 3 files changed, 93 insertions(+), 34 deletions(-) diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java index cfcc01a3f..884746b1c 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/ExcelUtil.java @@ -2,7 +2,6 @@ package cn.hutool.poi.excel; import cn.hutool.core.exceptions.DependencyException; import cn.hutool.core.io.FileUtil; -import cn.hutool.core.io.IoUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; @@ -10,6 +9,8 @@ import cn.hutool.poi.PoiChecker; import cn.hutool.poi.excel.cell.CellLocation; import cn.hutool.poi.excel.sax.Excel03SaxReader; import cn.hutool.poi.excel.sax.Excel07SaxReader; +import cn.hutool.poi.excel.sax.ExcelSaxReader; +import cn.hutool.poi.excel.sax.ExcelSaxUtil; import cn.hutool.poi.excel.sax.handler.RowHandler; import java.io.File; @@ -28,59 +29,92 @@ public class ExcelUtil { * 通过Sax方式读取Excel,同时支持03和07格式 * * @param path Excel文件路径 - * @param sheetIndex sheet序号 + * @param rid sheet rid,-1表示全部Sheet, 0表示第一个Sheet * @param rowHandler 行处理器 * @since 3.2.0 */ - public static void readBySax(String path, int sheetIndex, RowHandler rowHandler) { - readBySax(FileUtil.file(path), sheetIndex, rowHandler); + public static void readBySax(String path, int rid, RowHandler rowHandler) { + readBySax(FileUtil.file(path), rid, rowHandler); + } + + /** + * 通过Sax方式读取Excel,同时支持03和07格式 + * + * @param path Excel文件路径 + * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @param rowHandler 行处理器 + * @since 5.4.4 + */ + public static void readBySax(String path, String idOrRid, RowHandler rowHandler) { + readBySax(FileUtil.file(path), idOrRid, rowHandler); } /** * 通过Sax方式读取Excel,同时支持03和07格式 * * @param file Excel文件 - * @param sheetIndex sheet序号 + * @param rid sheet rid,-1表示全部Sheet, 0表示第一个Sheet * @param rowHandler 行处理器 * @since 3.2.0 */ - public static void readBySax(File file, int sheetIndex, RowHandler rowHandler) { - if (ExcelFileUtil.isXlsx(file)) { - read07BySax(file, sheetIndex, rowHandler); - } else { - read03BySax(file, sheetIndex, rowHandler); - } + public static void readBySax(File file, int rid, RowHandler rowHandler) { + final ExcelSaxReader reader = ExcelSaxUtil.createSaxReader(ExcelFileUtil.isXlsx(file), rowHandler); + reader.read(file, rid); + } + + /** + * 通过Sax方式读取Excel,同时支持03和07格式 + * + * @param file Excel文件 + * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @param rowHandler 行处理器 + * @since 5.4.4 + */ + public static void readBySax(File file, String idOrRid, RowHandler rowHandler) { + final ExcelSaxReader reader = ExcelSaxUtil.createSaxReader(ExcelFileUtil.isXlsx(file), rowHandler); + reader.read(file, idOrRid); } /** * 通过Sax方式读取Excel,同时支持03和07格式 * * @param in Excel流 - * @param sheetIndex sheet序号 + * @param rid sheet rid,-1表示全部Sheet, 0表示第一个Sheet * @param rowHandler 行处理器 * @since 3.2.0 */ - public static void readBySax(InputStream in, int sheetIndex, RowHandler rowHandler) { - in = IoUtil.toMarkSupportStream(in); - if (ExcelFileUtil.isXlsx(in)) { - read07BySax(in, sheetIndex, rowHandler); - } else { - read03BySax(in, sheetIndex, rowHandler); - } + public static void readBySax(InputStream in, int rid, RowHandler rowHandler) { + final ExcelSaxReader reader = ExcelSaxUtil.createSaxReader(ExcelFileUtil.isXlsx(in), rowHandler); + reader.read(in, rid); + } + + /** + * 通过Sax方式读取Excel,同时支持03和07格式 + * + * @param in Excel流 + * @param idOrRid Excel中的sheet id或者rid编号,rid必须加rId前缀,例如rId1,如果为-1处理所有编号的sheet + * @param rowHandler 行处理器 + * @since 5.4.4 + */ + public static void readBySax(InputStream in, String idOrRid, RowHandler rowHandler) { + final ExcelSaxReader reader = ExcelSaxUtil.createSaxReader(ExcelFileUtil.isXlsx(in), rowHandler); + reader.read(in, idOrRid); } /** * Sax方式读取Excel07 * * @param in 输入流 - * @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet + * @param rid Sheet rid,-1表示全部Sheet, 0表示第一个Sheet * @param rowHandler 行处理器 * @return {@link Excel07SaxReader} * @since 3.2.0 + * @deprecated 请使用 {@link #readBySax(InputStream, int, RowHandler)} */ - public static Excel07SaxReader read07BySax(InputStream in, int sheetIndex, RowHandler rowHandler) { + @Deprecated + public static Excel07SaxReader read07BySax(InputStream in, int rid, RowHandler rowHandler) { try { - return new Excel07SaxReader(rowHandler).read(in, sheetIndex); + return new Excel07SaxReader(rowHandler).read(in, rid); } catch (NoClassDefFoundError e) { throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG); } @@ -90,14 +124,16 @@ public class ExcelUtil { * Sax方式读取Excel07 * * @param file 文件 - * @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet + * @param rid Sheet rid,-1表示全部Sheet, 0表示第一个Sheet * @param rowHandler 行处理器 * @return {@link Excel07SaxReader} * @since 3.2.0 + * @deprecated 请使用 {@link #readBySax(File, int, RowHandler)} */ - public static Excel07SaxReader read07BySax(File file, int sheetIndex, RowHandler rowHandler) { + @Deprecated + public static Excel07SaxReader read07BySax(File file, int rid, RowHandler rowHandler) { try { - return new Excel07SaxReader(rowHandler).read(file, sheetIndex); + return new Excel07SaxReader(rowHandler).read(file, rid); } catch (NoClassDefFoundError e) { throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG); } @@ -107,14 +143,16 @@ public class ExcelUtil { * Sax方式读取Excel07 * * @param path 路径 - * @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet + * @param rid Sheet rid,-1表示全部Sheet, 0表示第一个Sheet * @param rowHandler 行处理器 * @return {@link Excel07SaxReader} * @since 3.2.0 + * @deprecated 请使用 {@link #readBySax(String, int, RowHandler)} */ - public static Excel07SaxReader read07BySax(String path, int sheetIndex, RowHandler rowHandler) { + @Deprecated + public static Excel07SaxReader read07BySax(String path, int rid, RowHandler rowHandler) { try { - return new Excel07SaxReader(rowHandler).read(path, sheetIndex); + return new Excel07SaxReader(rowHandler).read(path, rid); } catch (NoClassDefFoundError e) { throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG); } @@ -126,9 +164,11 @@ public class ExcelUtil { * @param in 输入流 * @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet * @param rowHandler 行处理器 - * @return {@link Excel07SaxReader} + * @return {@link Excel03SaxReader} * @since 3.2.0 + * @deprecated 请使用 {@link #readBySax(InputStream, int, RowHandler)} */ + @Deprecated public static Excel03SaxReader read03BySax(InputStream in, int sheetIndex, RowHandler rowHandler) { try { return new Excel03SaxReader(rowHandler).read(in, sheetIndex); @@ -145,7 +185,9 @@ public class ExcelUtil { * @param rowHandler 行处理器 * @return {@link Excel03SaxReader} * @since 3.2.0 + * @deprecated 请使用 {@link #readBySax(File, int, RowHandler)} */ + @Deprecated public static Excel03SaxReader read03BySax(File file, int sheetIndex, RowHandler rowHandler) { try { return new Excel03SaxReader(rowHandler).read(file, sheetIndex); @@ -162,7 +204,9 @@ public class ExcelUtil { * @param rowHandler 行处理器 * @return {@link Excel03SaxReader} * @since 3.2.0 + * @deprecated 请使用 {@link #readBySax(String, int, RowHandler)} */ + @Deprecated public static Excel03SaxReader read03BySax(String path, int sheetIndex, RowHandler rowHandler) { try { return new Excel03SaxReader(rowHandler).read(path, sheetIndex); diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java index 52b13ca49..c98b01334 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/ExcelSaxUtil.java @@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil; import cn.hutool.core.exceptions.DependencyException; import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.util.StrUtil; +import cn.hutool.poi.excel.sax.handler.RowHandler; import cn.hutool.poi.exceptions.POIException; import org.apache.poi.ooxml.util.SAXHelper; import org.apache.poi.ss.usermodel.DataFormatter; @@ -192,6 +193,20 @@ public class ExcelSaxUtil { return DateUtil.date(org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value, false)); } + /** + * 创建 {@link ExcelSaxReader} + * + * @param isXlsx 是否为xlsx格式(07格式) + * @param rowHandler 行处理器 + * @return {@link ExcelSaxReader} + * @since 5.4.4 + */ + public static ExcelSaxReader createSaxReader(boolean isXlsx, RowHandler rowHandler) { + return isXlsx + ? new Excel07SaxReader(rowHandler) + : new Excel03SaxReader(rowHandler); + } + /** * 获取数字类型值 * diff --git a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java b/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java index 88d34d4d0..888fa4e6a 100644 --- a/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java +++ b/hutool-poi/src/test/java/cn/hutool/poi/excel/test/ExcelSaxReadTest.java @@ -25,7 +25,7 @@ public class ExcelSaxReadTest { @Test public void excel07Test() { // 工具化快速读取 - ExcelUtil.read07BySax("aaa.xlsx", 0, createRowHandler()); + ExcelUtil.readBySax("aaa.xlsx", 0, createRowHandler()); } @Test @@ -33,7 +33,7 @@ public class ExcelSaxReadTest { Excel03SaxReader reader = new Excel03SaxReader(createRowHandler()); reader.read("aaa.xls", 1); // Console.log("Sheet index: [{}], Sheet name: [{}]", reader.getSheetIndex(), reader.getSheetName()); - ExcelUtil.read03BySax("aaa.xls", 1, createRowHandler()); + ExcelUtil.readBySax("aaa.xls", 1, createRowHandler()); } @Test @@ -60,7 +60,7 @@ public class ExcelSaxReadTest { private RowHandler createRowHandler() { return (sheetIndex, rowIndex, rowlist) -> { -// Console.log("[{}] [{}] {}", sheetIndex, rowIndex, rowlist); +// Console.log("[{}] [{}] {}", sheetIndex, rowIndex, rowlist); if (5 != rowIndex && 6 != rowIndex) { // 测试样例中除第五行、第六行都为非空行 Assert.assertTrue(CollUtil.isNotEmpty(rowlist)); @@ -105,14 +105,14 @@ public class ExcelSaxReadTest { @Test @Ignore - public void dateReadTest(){ + public void dateReadTest() { ExcelUtil.readBySax("d:/test/sax_date_test.xlsx", 0, (i, i1, list) -> Console.log(StrUtil.join(", ", list))); } @Test @Ignore - public void readBlankTest(){ + public void readBlankTest() { File file = new File("D:/test/b.xlsx"); ExcelUtil.readBySax(file, 0, (sheetIndex, rowIndex, rowList) -> rowList.forEach(Console::log)); From 1c19e612fe4be5c5eea8b00a4932e6e27a9d3392 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 01:43:09 +0800 Subject: [PATCH 03/28] rename to ConsoleTable --- .../cn/hutool/core/lang/ConsoleTable.java | 158 ++++++++++++++++ .../cn/hutool/core/lang/ConsoleTableUtil.java | 177 ------------------ .../cn/hutool/core/lang/ConsoleTableTest.java | 31 +++ 3 files changed, 189 insertions(+), 177 deletions(-) create mode 100644 hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java delete mode 100644 hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTableUtil.java create mode 100644 hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTableTest.java diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java new file mode 100644 index 000000000..1dd074066 --- /dev/null +++ b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java @@ -0,0 +1,158 @@ +package cn.hutool.core.lang; + +import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.StrUtil; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +/** + * 控制台打印表格工具 + * + * @author 孙宇 + * @since 5.4.4 + */ +public class ConsoleTable { + + private static final char ROW_LINE = '-'; + private static final char COLUMN_LINE = '|'; + private static final char CORNER = '+'; + private static final char SPACE = '\u3000'; + + /** + * 表格头信息 + */ + private final List> HEADER_LIST = new ArrayList<>(); + /** + * 表格体信息 + */ + private final List> BODY_LIST = new ArrayList<>(); + /** + * 每列最大字符个数 + */ + private List columnCharNumber; + + /** + * 添加头信息 + * + * @param titles 列名 + * @return 自身对象 + */ + public ConsoleTable addHeader(String... titles) { + if (columnCharNumber == null) { + columnCharNumber = new ArrayList<>(Collections.nCopies(titles.length, 0)); + } + List l = new ArrayList<>(); + fillColumns(l, titles); + HEADER_LIST.add(l); + return this; + } + + /** + * 添加体信息 + * + * @param values 列值 + * @return 自身对象 + */ + public ConsoleTable addBody(String... values) { + List l = new ArrayList<>(); + BODY_LIST.add(l); + fillColumns(l, values); + return this; + } + + /** + * 填充表格头或者体 + * + * @param l 被填充列表 + * @param columns 填充内容 + */ + private void fillColumns(List l, String[] columns) { + for (int i = 0; i < columns.length; i++) { + String column = columns[i]; + String col = Convert.toSBC(column); + l.add(col); + int width = col.length(); + if (width > columnCharNumber.get(i)) { + columnCharNumber.set(i, width); + } + } + } + + /** + * 获取表格字符串 + * + * @return 表格字符串 + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + fillBorder(sb); + for (List headers : HEADER_LIST) { + for (int i = 0; i < headers.size(); i++) { + if (i == 0) { + sb.append(COLUMN_LINE); + } + String header = headers.get(i); + sb.append(SPACE); + sb.append(header); + sb.append(SPACE); + int l = header.length(); + int lw = columnCharNumber.get(i); + if (lw > l) { + for (int j = 0; j < (lw - l); j++) { + sb.append(SPACE); + } + } + sb.append(COLUMN_LINE); + } + sb.append('\n'); + } + fillBorder(sb); + for (List bodys : BODY_LIST) { + for (int i = 0; i < bodys.size(); i++) { + if (i == 0) { + sb.append(COLUMN_LINE); + } + String body = bodys.get(i); + sb.append(SPACE); + sb.append(body); + sb.append(SPACE); + int l = body.length(); + int lw = columnCharNumber.get(i); + if (lw > l) { + for (int j = 0; j < (lw - l); j++) { + sb.append(SPACE); + } + } + sb.append(COLUMN_LINE); + } + sb.append('\n'); + } + fillBorder(sb); + return sb.toString(); + } + + /** + * 拼装边框 + * + * @param sb StringBuilder + */ + private void fillBorder(StringBuilder sb) { + sb.append(CORNER); + for (Integer width : columnCharNumber) { + sb.append(Convert.toSBC(StrUtil.fillAfter("", ROW_LINE, width + 2))); + sb.append(CORNER); + } + sb.append('\n'); + } + + /** + * 打印到控制台 + */ + public void print() { + Console.print(toString()); + } + +} \ No newline at end of file diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTableUtil.java b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTableUtil.java deleted file mode 100644 index f894dbf50..000000000 --- a/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTableUtil.java +++ /dev/null @@ -1,177 +0,0 @@ -package cn.hutool.core.lang; - -import cn.hutool.core.convert.Convert; -import cn.hutool.core.util.StrUtil; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -/** - * 控制台打印表格工具 - * - * @author 孙宇 - */ -public class ConsoleTableUtil { - /** - * 表格头信息 - */ - private final List> HEADER_LIST = new ArrayList<>(); - /** - * 表格体信息 - */ - private final List> BODY_LIST = new ArrayList<>(); - /** - * 每列最大字符个数 - */ - private List columnCharNumber; - - /** - * 测试 - * - * @param args - */ - public static void main(String[] args) { - ConsoleTableUtil t = new ConsoleTableUtil(); - t.addHeader("姓名", "年龄"); - t.addBody("张三", "15"); - t.addBody("李四", "29"); - t.addBody("王二麻子", "37"); - t.print(); - - t = new ConsoleTableUtil(); - t.addHeader("体温", "占比"); - t.addHeader("℃", "%"); - t.addBody("36.8", "10"); - t.addBody("37", "5"); - t.print(); - - t = new ConsoleTableUtil(); - t.addHeader("标题1", "标题2"); - t.addBody("12345", "混合321654asdfcSDF"); - t.addBody("sd e3ee ff22", "ff值"); - t.print(); - } - - /** - * 添加头信息 - * - * @param titles 列名 - * @return 自身对象 - */ - public ConsoleTableUtil addHeader(String... titles) { - if (columnCharNumber == null) { - columnCharNumber = new ArrayList<>(Collections.nCopies(titles.length, 0)); - } - List l = new ArrayList<>(); - HEADER_LIST.add(l); - fillColumns(l, titles); - return this; - } - - /** - * 添加体信息 - * - * @param values 列值 - * @return 自身对象 - */ - public ConsoleTableUtil addBody(String... values) { - List l = new ArrayList<>(); - BODY_LIST.add(l); - fillColumns(l, values); - return this; - } - - /** - * 填充表格头或者体 - * - * @param l - * @param columns - */ - private void fillColumns(List l, String[] columns) { - for (int i = 0; i < columns.length; i++) { - String column = columns[i]; - String col = Convert.toSBC(column); - l.add(col); - int width = col.length(); - if (width > columnCharNumber.get(i)) { - columnCharNumber.set(i, width); - } - } - } - - /** - * 获取表格字符串 - * - * @return 表格字符串 - */ - public String toString() { - StringBuilder sb = new StringBuilder(); - fillBorder(sb); - for (List headers : HEADER_LIST) { - for (int i = 0; i < headers.size(); i++) { - if (i == 0) { - sb.append('|'); - } - String header = headers.get(i); - sb.append(Convert.toSBC(" ")); - sb.append(header); - sb.append(Convert.toSBC(" ")); - int l = header.length(); - int lw = columnCharNumber.get(i); - if (lw > l) { - for (int j = 0; j < (lw - l); j++) { - sb.append(Convert.toSBC(" ")); - } - } - sb.append('|'); - } - sb.append('\n'); - } - fillBorder(sb); - for (List bodys : BODY_LIST) { - for (int i = 0; i < bodys.size(); i++) { - if (i == 0) { - sb.append('|'); - } - String body = bodys.get(i); - sb.append(Convert.toSBC(" ")); - sb.append(body); - sb.append(Convert.toSBC(" ")); - int l = body.length(); - int lw = columnCharNumber.get(i); - if (lw > l) { - for (int j = 0; j < (lw - l); j++) { - sb.append(Convert.toSBC(" ")); - } - } - sb.append('|'); - } - sb.append('\n'); - } - fillBorder(sb); - return sb.toString(); - } - - /** - * 拼装边框 - * - * @param sb - */ - private void fillBorder(StringBuilder sb) { - sb.append('*'); - for (Integer width : columnCharNumber) { - sb.append(Convert.toSBC(StrUtil.fillAfter("", '-', width + 2))); - sb.append('*'); - } - sb.append('\n'); - } - - /** - * 打印到控制台 - */ - public void print() { - Console.print(toString()); - } - -} \ No newline at end of file diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTableTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTableTest.java new file mode 100644 index 000000000..73a4f40c9 --- /dev/null +++ b/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTableTest.java @@ -0,0 +1,31 @@ +package cn.hutool.core.lang; + +import org.junit.Ignore; +import org.junit.Test; + +public class ConsoleTableTest { + + @Test + @Ignore + public void printTest(){ + ConsoleTable t = new ConsoleTable(); + t.addHeader("姓名", "年龄"); + t.addBody("张三", "15"); + t.addBody("李四", "29"); + t.addBody("王二麻子", "37"); + t.print(); + + t = new ConsoleTable(); + t.addHeader("体温", "占比"); + t.addHeader("℃", "%"); + t.addBody("36.8", "10"); + t.addBody("37", "5"); + t.print(); + + t = new ConsoleTable(); + t.addHeader("标题1", "标题2"); + t.addBody("12345", "混合321654asdfcSDF"); + t.addBody("sd e3ee ff22", "ff值"); + t.print(); + } +} From 61439c9138ac517cc17b86112f57697e8828359f Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 01:45:27 +0800 Subject: [PATCH 04/28] rename to ConsoleTable --- hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java index 54b2bba5c..09cef34be 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java @@ -522,7 +522,7 @@ public class RandomUtil { * * @return 随机颜色 * @since 4.1.5 - * @deprecated 使用{@link ImagUtil#randomColor()} + * @deprecated 使用{@link ImgUtil#randomColor()} */ public static Color randomColor() { final Random random = getRandom(); From 17cacc4a032c45e50e4a552c2b8edd4123778e3a Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 01:47:48 +0800 Subject: [PATCH 05/28] rename to ConsoleTable --- .../src/main/java/cn/hutool/core/util/RandomUtil.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java index 09cef34be..984a76867 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/RandomUtil.java @@ -48,8 +48,8 @@ public class RandomUtil { * ThreadLocalRandom是JDK 7之后提供并发产生随机数,能够解决多个线程发生的竞争争夺。 * *

- * 注意:此方法返回的{@link ThreadLocalRandom}不可以在多线程环境下共享对象,否则有重复随机数问题。 - * 见:https://www.jianshu.com/p/89dfe990295c + * 注意:此方法返回的{@link ThreadLocalRandom}不可以在多线程环境下共享对象,否则有重复随机数问题。 + * 见:https://www.jianshu.com/p/89dfe990295c *

* * @return {@link ThreadLocalRandom} @@ -522,9 +522,10 @@ public class RandomUtil { * * @return 随机颜色 * @since 4.1.5 - * @deprecated 使用{@link ImgUtil#randomColor()} + * @deprecated 使用ImgUtil.randomColor() */ - public static Color randomColor() { + @Deprecated + public static Color randomColor() { final Random random = getRandom(); return new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256)); } From 692a4a695b7b9fd9bd68ea7aa496079e3a989e52 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 09:09:18 +0800 Subject: [PATCH 06/28] fix comment --- .../hutool/poi/excel/sax/SheetRidReader.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java index 7af3c4884..abe9b7176 100644 --- a/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java +++ b/hutool-poi/src/main/java/cn/hutool/poi/excel/sax/SheetRidReader.java @@ -19,7 +19,7 @@ import java.util.Map; *
  * <sheet name="Sheet6" sheetId="4" r:id="6"/>
  * 
- * + *

* 读取结果为: * *

@@ -43,10 +43,11 @@ public class SheetRidReader extends DefaultHandler {
 	 * 读取Wordkbook的XML中sheet标签中sheetId和rid的对应关系
 	 *
 	 * @param xssfReader XSSF读取器
+	 * @return this
 	 */
-	public SheetRidReader read(XSSFReader xssfReader){
+	public SheetRidReader read(XSSFReader xssfReader) {
 		InputStream workbookData = null;
-		try{
+		try {
 			workbookData = xssfReader.getWorkbookData();
 			ExcelSaxUtil.readFrom(workbookData, this);
 		} catch (InvalidFormatException e) {
@@ -65,7 +66,7 @@ public class SheetRidReader extends DefaultHandler {
 	 * @param sheetId Sheet的ID
 	 * @return rid
 	 */
-	public String getRidBySheetId(String sheetId){
+	public String getRidBySheetId(String sheetId) {
 		return ID_RID_MAP.get(sheetId);
 	}
 
@@ -75,19 +76,19 @@ public class SheetRidReader extends DefaultHandler {
 	 * @param sheetName Sheet的name
 	 * @return rid
 	 */
-	public String getRidByName(String sheetName){
+	public String getRidByName(String sheetName) {
 		return NAME_RID_MAP.get(sheetName);
 	}
 
 	@Override
 	public void startElement(String uri, String localName, String qName, Attributes attributes) {
-		if(TAG_NAME.equalsIgnoreCase(localName)){
+		if (TAG_NAME.equalsIgnoreCase(localName)) {
 			final int length = attributes.getLength();
 			String sheetId = null;
 			String rid = null;
 			String name = null;
 			for (int i = 0; i < length; i++) {
-				switch (attributes.getLocalName(i)){
+				switch (attributes.getLocalName(i)) {
 					case SHEET_ID_ATTR:
 						sheetId = attributes.getValue(i);
 						break;
@@ -98,10 +99,10 @@ public class SheetRidReader extends DefaultHandler {
 						name = attributes.getValue(i);
 						break;
 				}
-				if(StrUtil.isNotEmpty(sheetId)){
+				if (StrUtil.isNotEmpty(sheetId)) {
 					ID_RID_MAP.put(sheetId, rid);
 				}
-				if(StrUtil.isNotEmpty(name)){
+				if (StrUtil.isNotEmpty(name)) {
 					NAME_RID_MAP.put(name, rid);
 				}
 			}

From f6a18afcba2976ee100a4c2b0cce13fedd6bb4f5 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Wed, 30 Sep 2020 10:47:10 +0800
Subject: [PATCH 07/28] fix test

---
 hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java
index 9243a34a1..87aebdb5a 100644
--- a/hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java
+++ b/hutool-core/src/test/java/cn/hutool/core/img/ImgUtilTest.java
@@ -25,7 +25,9 @@ public class ImgUtilTest {
 	@Test
 	@Ignore
 	public void scaleTest2() {
-		ImgUtil.scale(FileUtil.file("e:/pic/test.jpg"), FileUtil.file("e:/pic/test_result.jpg"), 0.8f);
+		ImgUtil.scale(
+				FileUtil.file("d:/test/2.png"),
+				FileUtil.file("d:/test/2_result.jpg"), 600, 337, null);
 	}
 
 	@Test

From 61c0633da715d111512af2871a9d6ad2cf6edde2 Mon Sep 17 00:00:00 2001
From: Looly 
Date: Wed, 30 Sep 2020 11:30:10 +0800
Subject: [PATCH 08/28] add readBySax

---
 CHANGELOG.md                                  |  1 +
 .../java/cn/hutool/core/util/XmlUtil.java     | 97 +++++++++++++++++++
 .../java/cn/hutool/core/util/XmlUtilTest.java | 15 +++
 3 files changed, 113 insertions(+)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 6a4932d02..f9b76c248 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -32,6 +32,7 @@
 * 【core   】     NumberUtil增加isPowerOfTwo方法(pr#1132@Github)
 * 【core   】     优化BooleanUtil的校验逻辑(pr#1137@Github)
 * 【poi    】     改进sax方式读取逻辑,支持sheetId(issue#1141@Github)
+* 【core   】     XmlUtil增加readBySax方法
 
 ### Bug修复
 * 【crypto 】     修复SM2验签后无法解密问题(issue#I1W0VP@Gitee)
diff --git a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java
index 4b9d80a93..357c859c7 100644
--- a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java
@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.exceptions.UtilException;
 import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IORuntimeException;
 import cn.hutool.core.io.IoUtil;
 import cn.hutool.core.lang.Assert;
 import cn.hutool.core.map.BiMap;
@@ -13,7 +14,11 @@ import org.w3c.dom.Element;
 import org.w3c.dom.NamedNodeMap;
 import org.w3c.dom.Node;
 import org.w3c.dom.NodeList;
+import org.xml.sax.ContentHandler;
 import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+import org.xml.sax.XMLReader;
+import org.xml.sax.helpers.DefaultHandler;
 
 import javax.xml.XMLConstants;
 import javax.xml.namespace.NamespaceContext;
@@ -21,6 +26,8 @@ import javax.xml.namespace.QName;
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
 import javax.xml.transform.OutputKeys;
 import javax.xml.transform.Result;
 import javax.xml.transform.Source;
@@ -76,6 +83,10 @@ public class XmlUtil {
 	 * 是否打开命名空间支持
 	 */
 	private static boolean namespaceAware = true;
+	/**
+	 * Sax读取器工厂缓存
+	 */
+	private static SAXParserFactory factory;
 
 	/**
 	 * 禁用默认的DocumentBuilderFactory,禁用后如果有第三方的实现(如oracle的xdb包中的xmlparse),将会自动加载实现。
@@ -184,6 +195,92 @@ public class XmlUtil {
 		}
 	}
 
+	/**
+	 * 使用Sax方式读取指定的XML
+ * 如果用户传入的contentHandler为{@link DefaultHandler},则其接口都会被处理 + * + * @param file XML源文件,使用后自动关闭 + * @param contentHandler XML流处理器,用于按照Element处理xml + * @since 5.4.4 + */ + public static void readBySax(File file, ContentHandler contentHandler) { + InputStream in = null; + try{ + in = FileUtil.getInputStream(file); + readBySax(new InputSource(in), contentHandler); + } finally { + IoUtil.close(in); + } + } + + /** + * 使用Sax方式读取指定的XML
+ * 如果用户传入的contentHandler为{@link DefaultHandler},则其接口都会被处理 + * + * @param reader XML源Reader,使用后自动关闭 + * @param contentHandler XML流处理器,用于按照Element处理xml + * @since 5.4.4 + */ + public static void readBySax(Reader reader, ContentHandler contentHandler) { + try{ + readBySax(new InputSource(reader), contentHandler); + } finally { + IoUtil.close(reader); + } + } + + /** + * 使用Sax方式读取指定的XML
+ * 如果用户传入的contentHandler为{@link DefaultHandler},则其接口都会被处理 + * + * @param source XML源流,使用后自动关闭 + * @param contentHandler XML流处理器,用于按照Element处理xml + * @since 5.4.4 + */ + public static void readBySax(InputStream source, ContentHandler contentHandler) { + try{ + readBySax(new InputSource(source), contentHandler); + } finally { + IoUtil.close(source); + } + } + + /** + * 使用Sax方式读取指定的XML
+ * 如果用户传入的contentHandler为{@link DefaultHandler},则其接口都会被处理 + * + * @param source XML源,可以是文件、流、路径等 + * @param contentHandler XML流处理器,用于按照Element处理xml + * @since 5.4.4 + */ + public static void readBySax(InputSource source, ContentHandler contentHandler) { + // 1.获取解析工厂 + if (null == factory) { + factory = SAXParserFactory.newInstance(); + factory.setValidating(false); + factory.setNamespaceAware(namespaceAware); + } + // 2.从解析工厂获取解析器 + final SAXParser parse; + XMLReader reader; + try { + parse = factory.newSAXParser(); + if (contentHandler instanceof DefaultHandler) { + parse.parse(source, (DefaultHandler) contentHandler); + return; + } + + // 3.得到解读器 + reader = parse.getXMLReader(); + reader.setContentHandler(contentHandler); + reader.parse(source); + } catch (ParserConfigurationException | SAXException e) { + throw new UtilException(e); + } catch (IOException e) { + throw new IORuntimeException(e); + } + } + /** * 将String类型的XML转换为XML文档 * diff --git a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java index 231de5133..aaa9527ca 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java @@ -9,10 +9,13 @@ import org.junit.Assert; import org.junit.Ignore; import org.junit.Test; import org.w3c.dom.Document; +import org.xml.sax.Attributes; +import org.xml.sax.helpers.DefaultHandler; import javax.xml.xpath.XPathConstants; import java.util.LinkedHashMap; import java.util.Map; +import java.util.Set; /** * {@link XmlUtil} 工具类 @@ -148,6 +151,18 @@ public class XmlUtilTest { Assert.assertNotNull(doc); } + @Test + public void readBySaxTest(){ + final Set eles = CollUtil.newHashSet( + "returnsms", "returnstatus", "message", "remainpoint", "taskID", "successCounts"); + XmlUtil.readBySax(ResourceUtil.getStream("test.xml"), new DefaultHandler(){ + @Override + public void startElement(String uri, String localName, String qName, Attributes attributes) { + Assert.assertTrue(eles.contains(localName)); + } + }); + } + @Test public void mapToXmlTestWithOmitXmlDeclaration() { From 06e46ffb99374ee8b66bd1623eb11a2d6e64bda2 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 11:39:52 +0800 Subject: [PATCH 09/28] update dependency --- hutool-db/pom.xml | 4 ++-- hutool-extra/pom.xml | 6 +++--- hutool-script/pom.xml | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 991444907..60350b5b4 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -19,9 +19,9 @@ 0.9.5.5 - 2.7.0 + 2.8.0 9.0.30 - 1.1.23 + 1.1.24 2.4.13 3.12.7 3.32.3.2 diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 454c0df47..16c373136 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -19,15 +19,15 @@ 2.2 - 3.2.0.RELEASE + 3.2.1.RELEASE 1.3.0 2.3.30 4.9.01 3.0.11.RELEASE 1.6.2 0.1.55 - 3.4.0 - 3.6 + 3.4.1 + 3.7 5.1.1 4.0.1 2.3.4.RELEASE diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 0bc5d4c63..73152aac0 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -18,7 +18,7 @@ 2.7.2 3.0.1 - 3.0.2 + 3.0.6 From 7038498addb8b6a93cea4e3c4b34113f1a798dab Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 11:42:40 +0800 Subject: [PATCH 10/28] release 5.4.4 --- hutool-all/pom.xml | 2 +- hutool-aop/pom.xml | 2 +- hutool-bloomFilter/pom.xml | 2 +- hutool-bom/pom.xml | 2 +- hutool-cache/pom.xml | 2 +- hutool-captcha/pom.xml | 2 +- hutool-core/pom.xml | 2 +- hutool-cron/pom.xml | 2 +- hutool-crypto/pom.xml | 2 +- hutool-db/pom.xml | 2 +- hutool-dfa/pom.xml | 2 +- hutool-extra/pom.xml | 2 +- hutool-http/pom.xml | 2 +- hutool-json/pom.xml | 2 +- hutool-log/pom.xml | 2 +- hutool-poi/pom.xml | 2 +- hutool-script/pom.xml | 2 +- hutool-setting/pom.xml | 2 +- hutool-socket/pom.xml | 2 +- hutool-system/pom.xml | 2 +- pom.xml | 2 +- 21 files changed, 21 insertions(+), 21 deletions(-) diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 9a7e395bd..e6d55b197 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 204c892b4..c043e86dc 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 7f219864b..1a0d68e49 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 47f6c2d47..f70c3e4a0 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 9fbc93e04..20d48dd1e 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 36af6c3e6..c3e1a3f4e 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index c4d57ae21..99daa68d0 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index e1fb492f9..0c1a39b86 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index e84f71c45..457e0d754 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 60350b5b4..1ef59e31a 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 07dc1656d..9a507798d 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index 16c373136..ddd6698ea 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index f5ca543b9..b04c43424 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index 617a9ca00..c9287aa1f 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 19429e26e..21e407854 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 6d74e4a4b..8cc9fbc50 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 73152aac0..1a8f870b5 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 7ab60de80..17c73463b 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index 19509870c..bbda29e1b 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 93fb286bb..31e2a955f 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool-system diff --git a/pom.xml b/pom.xml index 534a944a2..ea438c3b7 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.4-SNAPSHOT + 5.4.4 hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool From 2a24b7fd6e00ba7990fa22a37aed95af513eafe6 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 11:50:26 +0800 Subject: [PATCH 11/28] fox word --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 949c6a321..a14a97bf5 100644 --- a/README.md +++ b/README.md @@ -141,7 +141,7 @@ compile 'cn.hutool:hutool-all:5.4.4' ### 编译安装 -访问Hutool的码云主页:[https://gitee.com/loolly/hutool](https://gitee.com/loolly/hutool) 下载整个项目源码(v5-master或v5-dev分支都可)然后进入Hutool项目目录执行: +访问Hutool的Gitee主页:[https://gitee.com/loolly/hutool](https://gitee.com/loolly/hutool) 下载整个项目源码(v5-master或v5-dev分支都可)然后进入Hutool项目目录执行: ```sh ./hutool.sh install @@ -166,7 +166,7 @@ Hutool的源码分为两个分支,功能如下: 提交问题反馈请说明正在使用的JDK版本呢、Hutool版本和相关依赖库版本。 -- [码云Gitee issue](https://gitee.com/loolly/hutool/issues) +- [Gitee issue](https://gitee.com/loolly/hutool/issues) - [Github issue](https://github.com/looly/hutool/issues) @@ -177,14 +177,14 @@ Hutool的源码分为两个分支,功能如下: 3. 修改代码(记得一定要修改v5-dev分支) 4. commit后push到自己的库(v5-dev分支) 5. 登录Gitee或Github在你首页可以看到一个 pull request 按钮,点击它,填写一些说明信息,然后提交即可。 -6. 等待作者合并 +6. 等待维护者合并 ### PR遵照的原则 -Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过作者是一个强迫症患者,为了照顾病人,需要提交的pr(pull request)符合一些规范,规范如下: +Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过维护者是一个强迫症患者,为了照顾病人,需要提交的pr(pull request)符合一些规范,规范如下: 1. 注释完备,尤其每个新增的方法应按照Java文档规范标明方法说明、参数说明、返回值说明等信息,必要时请添加单元测试,如果愿意,也可以加上你的大名。 -2. Hutool的缩进按照Eclipse(~~不要跟我说IDEA多好用,作者非常懒,学不会~~,IDEA真香,改了Eclipse快捷键后舒服多了)默认(tab)缩进,所以请遵守(不要和我争执空格与tab的问题,这是一个病人的习惯)。 +2. Hutool的缩进按照Eclipse(~~不要跟我说IDEA多好用,维护者非常懒,学不会~~,IDEA真香,改了Eclipse快捷键后舒服多了)默认(tab)缩进,所以请遵守(不要和我争执空格与tab的问题,这是一个病人的习惯)。 3. 新加的方法不要使用第三方库的方法,Hutool遵循无依赖原则(除非在extra模块中加方法工具)。 4. 请pull request到`v5-dev`分支。Hutool在5.x版本后使用了新的分支:`v5-master`是主分支,表示已经发布中央库的版本,这个分支不允许pr,也不允许修改。 @@ -192,7 +192,7 @@ Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过作者是一 ## 捐赠 -如果你觉得Hutool不错,可以捐赠请作者吃包辣条~,在此表示感谢^_^。 +如果你觉得Hutool不错,可以捐赠请维护者吃包辣条~,在此表示感谢^_^。 点击以下链接,将页面拉到最下方点击“捐赠”即可。 From 7c23aadb9e1e7214b57300432bc252e3284efcc5 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 12:04:01 +0800 Subject: [PATCH 12/28] prepare 5.4.5 --- CHANGELOG.md | 8 ++++++++ README-EN.md | 8 ++++---- README.md | 8 ++++---- bin/version.txt | 2 +- docs/js/version.js | 2 +- hutool-all/pom.xml | 2 +- hutool-aop/pom.xml | 2 +- hutool-bloomFilter/pom.xml | 2 +- hutool-bom/pom.xml | 2 +- hutool-cache/pom.xml | 2 +- hutool-captcha/pom.xml | 2 +- hutool-core/pom.xml | 2 +- hutool-cron/pom.xml | 2 +- hutool-crypto/pom.xml | 2 +- hutool-db/pom.xml | 2 +- hutool-dfa/pom.xml | 2 +- hutool-extra/pom.xml | 2 +- hutool-http/pom.xml | 2 +- hutool-json/pom.xml | 2 +- hutool-log/pom.xml | 2 +- hutool-poi/pom.xml | 2 +- hutool-script/pom.xml | 2 +- hutool-setting/pom.xml | 2 +- hutool-socket/pom.xml | 2 +- hutool-system/pom.xml | 2 +- pom.xml | 2 +- 26 files changed, 39 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9b76c248..5a61cd285 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,14 @@ ------------------------------------------------------------------------------------------------------------- +# 5.4.5 (2020-09-30) + +### 新特性 + +### Bug修复 + +------------------------------------------------------------------------------------------------------------- + # 5.4.4 (2020-09-28) ### 新特性 diff --git a/README-EN.md b/README-EN.md index c3ce780e2..109d59373 100644 --- a/README-EN.md +++ b/README-EN.md @@ -120,19 +120,19 @@ Each module can be introduced individually, or all modules can be introduced by cn.hutool hutool-all - 5.4.4 + 5.4.5 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.4.4' +compile 'cn.hutool:hutool-all:5.4.5' ``` ## Download -- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.4/) -- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.4/) +- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.5/) +- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.5/) > note: > Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available. diff --git a/README.md b/README.md index a14a97bf5..ffb4b58c4 100644 --- a/README.md +++ b/README.md @@ -119,21 +119,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.4.4 + 5.4.5 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.4.4' +compile 'cn.hutool:hutool-all:5.4.5' ``` ### 非Maven项目 点击以下任一链接,下载`hutool-all-X.X.X.jar`即可: -- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.4/) -- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.4/) +- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.4.5/) +- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.5/) > 注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index 426c1c179..8ce222e90 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.4.4 +5.4.5 diff --git a/docs/js/version.js b/docs/js/version.js index 876d3bc42..ca23d3c78 100644 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.4.4' \ No newline at end of file +var version = '5.4.5' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index e6d55b197..9c635dedf 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index c043e86dc..ba86c1b4a 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 1a0d68e49..dd544604e 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index f70c3e4a0..4b0d9b363 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 20d48dd1e..ab7b31fd8 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index c3e1a3f4e..b4dd92449 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 99daa68d0..42bebd745 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-core diff --git a/hutool-cron/pom.xml b/hutool-cron/pom.xml index 0c1a39b86..f4f0368c7 100644 --- a/hutool-cron/pom.xml +++ b/hutool-cron/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-cron diff --git a/hutool-crypto/pom.xml b/hutool-crypto/pom.xml index 457e0d754..25acea0a2 100644 --- a/hutool-crypto/pom.xml +++ b/hutool-crypto/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-crypto diff --git a/hutool-db/pom.xml b/hutool-db/pom.xml index 1ef59e31a..99518169b 100644 --- a/hutool-db/pom.xml +++ b/hutool-db/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-db diff --git a/hutool-dfa/pom.xml b/hutool-dfa/pom.xml index 9a507798d..1d2a09ab2 100644 --- a/hutool-dfa/pom.xml +++ b/hutool-dfa/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-dfa diff --git a/hutool-extra/pom.xml b/hutool-extra/pom.xml index ddd6698ea..f91f5ac87 100644 --- a/hutool-extra/pom.xml +++ b/hutool-extra/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-extra diff --git a/hutool-http/pom.xml b/hutool-http/pom.xml index b04c43424..a7b33873e 100644 --- a/hutool-http/pom.xml +++ b/hutool-http/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-http diff --git a/hutool-json/pom.xml b/hutool-json/pom.xml index c9287aa1f..b84f23bec 100644 --- a/hutool-json/pom.xml +++ b/hutool-json/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-json diff --git a/hutool-log/pom.xml b/hutool-log/pom.xml index 21e407854..3d15e4203 100644 --- a/hutool-log/pom.xml +++ b/hutool-log/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-log diff --git a/hutool-poi/pom.xml b/hutool-poi/pom.xml index 8cc9fbc50..47dcd4ea4 100644 --- a/hutool-poi/pom.xml +++ b/hutool-poi/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-poi diff --git a/hutool-script/pom.xml b/hutool-script/pom.xml index 1a8f870b5..995789f43 100644 --- a/hutool-script/pom.xml +++ b/hutool-script/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-script diff --git a/hutool-setting/pom.xml b/hutool-setting/pom.xml index 17c73463b..00e487784 100644 --- a/hutool-setting/pom.xml +++ b/hutool-setting/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-setting diff --git a/hutool-socket/pom.xml b/hutool-socket/pom.xml index bbda29e1b..459441938 100644 --- a/hutool-socket/pom.xml +++ b/hutool-socket/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-socket diff --git a/hutool-system/pom.xml b/hutool-system/pom.xml index 31e2a955f..8110b4903 100644 --- a/hutool-system/pom.xml +++ b/hutool-system/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool-system diff --git a/pom.xml b/pom.xml index ea438c3b7..57c5d9379 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ cn.hutool hutool-parent - 5.4.4 + 5.4.5-SNAPSHOT hutool Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。 https://github.com/looly/hutool From 93877205c579cb0584d4049412e90623a6d13055 Mon Sep 17 00:00:00 2001 From: SunYu Date: Wed, 30 Sep 2020 13:50:13 +0800 Subject: [PATCH 13/28] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cn/hutool/core/lang/ConsoleTable.java | 256 +++++++++--------- .../cn/hutool/core/lang/ConsoleTableTest.java | 46 ++-- 2 files changed, 149 insertions(+), 153 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java index 1dd074066..a65fae6a7 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java @@ -15,144 +15,136 @@ import java.util.List; */ public class ConsoleTable { - private static final char ROW_LINE = '-'; - private static final char COLUMN_LINE = '|'; - private static final char CORNER = '+'; - private static final char SPACE = '\u3000'; + private static final char ROW_LINE = '-'; + private static final char COLUMN_LINE = '|'; + private static final char CORNER = '+'; + private static final char SPACE = '\u3000'; + private static final char LF = '\n'; - /** - * 表格头信息 - */ - private final List> HEADER_LIST = new ArrayList<>(); - /** - * 表格体信息 - */ - private final List> BODY_LIST = new ArrayList<>(); - /** - * 每列最大字符个数 - */ - private List columnCharNumber; + /** + * 表格头信息 + */ + private final List> HEADER_LIST = new ArrayList<>(); + /** + * 表格体信息 + */ + private final List> BODY_LIST = new ArrayList<>(); + /** + * 每列最大字符个数 + */ + private List columnCharNumber; - /** - * 添加头信息 - * - * @param titles 列名 - * @return 自身对象 - */ - public ConsoleTable addHeader(String... titles) { - if (columnCharNumber == null) { - columnCharNumber = new ArrayList<>(Collections.nCopies(titles.length, 0)); - } - List l = new ArrayList<>(); - fillColumns(l, titles); - HEADER_LIST.add(l); - return this; - } + /** + * 添加头信息 + * + * @param titles 列名 + * @return 自身对象 + */ + public ConsoleTable addHeader(String... titles) { + if (columnCharNumber == null) { + columnCharNumber = new ArrayList<>(Collections.nCopies(titles.length, 0)); + } + List l = new ArrayList<>(); + fillColumns(l, titles); + HEADER_LIST.add(l); + return this; + } - /** - * 添加体信息 - * - * @param values 列值 - * @return 自身对象 - */ - public ConsoleTable addBody(String... values) { - List l = new ArrayList<>(); - BODY_LIST.add(l); - fillColumns(l, values); - return this; - } + /** + * 添加体信息 + * + * @param values 列值 + * @return 自身对象 + */ + public ConsoleTable addBody(String... values) { + List l = new ArrayList<>(); + BODY_LIST.add(l); + fillColumns(l, values); + return this; + } - /** - * 填充表格头或者体 - * - * @param l 被填充列表 - * @param columns 填充内容 - */ - private void fillColumns(List l, String[] columns) { - for (int i = 0; i < columns.length; i++) { - String column = columns[i]; - String col = Convert.toSBC(column); - l.add(col); - int width = col.length(); - if (width > columnCharNumber.get(i)) { - columnCharNumber.set(i, width); - } - } - } + /** + * 填充表格头或者体 + * + * @param l 被填充列表 + * @param columns 填充内容 + */ + private void fillColumns(List l, String[] columns) { + for (int i = 0; i < columns.length; i++) { + String column = columns[i]; + String col = Convert.toSBC(column); + l.add(col); + int width = col.length(); + if (width > columnCharNumber.get(i)) { + columnCharNumber.set(i, width); + } + } + } - /** - * 获取表格字符串 - * - * @return 表格字符串 - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - fillBorder(sb); - for (List headers : HEADER_LIST) { - for (int i = 0; i < headers.size(); i++) { - if (i == 0) { - sb.append(COLUMN_LINE); - } - String header = headers.get(i); - sb.append(SPACE); - sb.append(header); - sb.append(SPACE); - int l = header.length(); - int lw = columnCharNumber.get(i); - if (lw > l) { - for (int j = 0; j < (lw - l); j++) { - sb.append(SPACE); - } - } - sb.append(COLUMN_LINE); - } - sb.append('\n'); - } - fillBorder(sb); - for (List bodys : BODY_LIST) { - for (int i = 0; i < bodys.size(); i++) { - if (i == 0) { - sb.append(COLUMN_LINE); - } - String body = bodys.get(i); - sb.append(SPACE); - sb.append(body); - sb.append(SPACE); - int l = body.length(); - int lw = columnCharNumber.get(i); - if (lw > l) { - for (int j = 0; j < (lw - l); j++) { - sb.append(SPACE); - } - } - sb.append(COLUMN_LINE); - } - sb.append('\n'); - } - fillBorder(sb); - return sb.toString(); - } + /** + * 获取表格字符串 + * + * @return 表格字符串 + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + fillBorder(sb); + fillRow(sb, HEADER_LIST); + fillBorder(sb); + fillRow(sb, BODY_LIST); + fillBorder(sb); + return sb.toString(); + } - /** - * 拼装边框 - * - * @param sb StringBuilder - */ - private void fillBorder(StringBuilder sb) { - sb.append(CORNER); - for (Integer width : columnCharNumber) { - sb.append(Convert.toSBC(StrUtil.fillAfter("", ROW_LINE, width + 2))); - sb.append(CORNER); - } - sb.append('\n'); - } + /** + * 填充表头或者表体信息 + * + * @param sb + * @param list 表头列表或者表体列表 + */ + private void fillRow(StringBuilder sb, List> list) { + for (List r : list) { + for (int i = 0; i < r.size(); i++) { + if (i == 0) { + sb.append(COLUMN_LINE); + } + String header = r.get(i); + sb.append(SPACE); + sb.append(header); + sb.append(SPACE); + int l = header.length(); + int lw = columnCharNumber.get(i); + if (lw > l) { + for (int j = 0; j < (lw - l); j++) { + sb.append(SPACE); + } + } + sb.append(COLUMN_LINE); + } + sb.append(LF); + } + } - /** - * 打印到控制台 - */ - public void print() { - Console.print(toString()); - } + /** + * 拼装边框 + * + * @param sb StringBuilder + */ + private void fillBorder(StringBuilder sb) { + sb.append(CORNER); + for (Integer width : columnCharNumber) { + sb.append(Convert.toSBC(StrUtil.fillAfter("", ROW_LINE, width + 2))); + sb.append(CORNER); + } + sb.append(LF); + } + + /** + * 打印到控制台 + */ + public void print() { + Console.print(toString()); + } } \ No newline at end of file diff --git a/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTableTest.java b/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTableTest.java index 73a4f40c9..b92ddfd72 100644 --- a/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTableTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/lang/ConsoleTableTest.java @@ -5,27 +5,31 @@ import org.junit.Test; public class ConsoleTableTest { - @Test - @Ignore - public void printTest(){ - ConsoleTable t = new ConsoleTable(); - t.addHeader("姓名", "年龄"); - t.addBody("张三", "15"); - t.addBody("李四", "29"); - t.addBody("王二麻子", "37"); - t.print(); + @Test + @Ignore + public void printTest() { + ConsoleTable t = new ConsoleTable(); + t.addHeader("姓名", "年龄"); + t.addBody("张三", "15"); + t.addBody("李四", "29"); + t.addBody("王二麻子", "37"); + t.print(); - t = new ConsoleTable(); - t.addHeader("体温", "占比"); - t.addHeader("℃", "%"); - t.addBody("36.8", "10"); - t.addBody("37", "5"); - t.print(); + Console.log(); - t = new ConsoleTable(); - t.addHeader("标题1", "标题2"); - t.addBody("12345", "混合321654asdfcSDF"); - t.addBody("sd e3ee ff22", "ff值"); - t.print(); - } + t = new ConsoleTable(); + t.addHeader("体温", "占比"); + t.addHeader("℃", "%"); + t.addBody("36.8", "10"); + t.addBody("37", "5"); + t.print(); + + Console.log(); + + t = new ConsoleTable(); + t.addHeader("标题1", "标题2"); + t.addBody("12345", "混合321654asdfcSDF"); + t.addBody("sd e3ee ff22", "ff值"); + t.print(); + } } From 49d5fb471f0e2466f5ba84665a2b52f748f605ec Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 15:37:13 +0800 Subject: [PATCH 14/28] fix code --- .../cn/hutool/core/lang/ConsoleTable.java | 247 +++++++++--------- 1 file changed, 124 insertions(+), 123 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java index a65fae6a7..d219655eb 100644 --- a/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java +++ b/hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java @@ -1,6 +1,7 @@ package cn.hutool.core.lang; import cn.hutool.core.convert.Convert; +import cn.hutool.core.util.CharUtil; import cn.hutool.core.util.StrUtil; import java.util.ArrayList; @@ -15,136 +16,136 @@ import java.util.List; */ public class ConsoleTable { - private static final char ROW_LINE = '-'; - private static final char COLUMN_LINE = '|'; - private static final char CORNER = '+'; - private static final char SPACE = '\u3000'; - private static final char LF = '\n'; + private static final char ROW_LINE = '-'; + private static final char COLUMN_LINE = '|'; + private static final char CORNER = '+'; + private static final char SPACE = '\u3000'; + private static final char LF = CharUtil.LF; - /** - * 表格头信息 - */ - private final List> HEADER_LIST = new ArrayList<>(); - /** - * 表格体信息 - */ - private final List> BODY_LIST = new ArrayList<>(); - /** - * 每列最大字符个数 - */ - private List columnCharNumber; + /** + * 表格头信息 + */ + private final List> HEADER_LIST = new ArrayList<>(); + /** + * 表格体信息 + */ + private final List> BODY_LIST = new ArrayList<>(); + /** + * 每列最大字符个数 + */ + private List columnCharNumber; - /** - * 添加头信息 - * - * @param titles 列名 - * @return 自身对象 - */ - public ConsoleTable addHeader(String... titles) { - if (columnCharNumber == null) { - columnCharNumber = new ArrayList<>(Collections.nCopies(titles.length, 0)); - } - List l = new ArrayList<>(); - fillColumns(l, titles); - HEADER_LIST.add(l); - return this; - } + /** + * 添加头信息 + * + * @param titles 列名 + * @return 自身对象 + */ + public ConsoleTable addHeader(String... titles) { + if (columnCharNumber == null) { + columnCharNumber = new ArrayList<>(Collections.nCopies(titles.length, 0)); + } + List l = new ArrayList<>(); + fillColumns(l, titles); + HEADER_LIST.add(l); + return this; + } - /** - * 添加体信息 - * - * @param values 列值 - * @return 自身对象 - */ - public ConsoleTable addBody(String... values) { - List l = new ArrayList<>(); - BODY_LIST.add(l); - fillColumns(l, values); - return this; - } + /** + * 添加体信息 + * + * @param values 列值 + * @return 自身对象 + */ + public ConsoleTable addBody(String... values) { + List l = new ArrayList<>(); + BODY_LIST.add(l); + fillColumns(l, values); + return this; + } - /** - * 填充表格头或者体 - * - * @param l 被填充列表 - * @param columns 填充内容 - */ - private void fillColumns(List l, String[] columns) { - for (int i = 0; i < columns.length; i++) { - String column = columns[i]; - String col = Convert.toSBC(column); - l.add(col); - int width = col.length(); - if (width > columnCharNumber.get(i)) { - columnCharNumber.set(i, width); - } - } - } + /** + * 填充表格头或者体 + * + * @param l 被填充列表 + * @param columns 填充内容 + */ + private void fillColumns(List l, String[] columns) { + for (int i = 0; i < columns.length; i++) { + String column = columns[i]; + String col = Convert.toSBC(column); + l.add(col); + int width = col.length(); + if (width > columnCharNumber.get(i)) { + columnCharNumber.set(i, width); + } + } + } - /** - * 获取表格字符串 - * - * @return 表格字符串 - */ - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - fillBorder(sb); - fillRow(sb, HEADER_LIST); - fillBorder(sb); - fillRow(sb, BODY_LIST); - fillBorder(sb); - return sb.toString(); - } + /** + * 获取表格字符串 + * + * @return 表格字符串 + */ + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + fillBorder(sb); + fillRow(sb, HEADER_LIST); + fillBorder(sb); + fillRow(sb, BODY_LIST); + fillBorder(sb); + return sb.toString(); + } - /** - * 填充表头或者表体信息 - * - * @param sb - * @param list 表头列表或者表体列表 - */ - private void fillRow(StringBuilder sb, List> list) { - for (List r : list) { - for (int i = 0; i < r.size(); i++) { - if (i == 0) { - sb.append(COLUMN_LINE); - } - String header = r.get(i); - sb.append(SPACE); - sb.append(header); - sb.append(SPACE); - int l = header.length(); - int lw = columnCharNumber.get(i); - if (lw > l) { - for (int j = 0; j < (lw - l); j++) { - sb.append(SPACE); - } - } - sb.append(COLUMN_LINE); - } - sb.append(LF); - } - } + /** + * 填充表头或者表体信息 + * + * @param sb + * @param list 表头列表或者表体列表 + */ + private void fillRow(StringBuilder sb, List> list) { + for (List r : list) { + for (int i = 0; i < r.size(); i++) { + if (i == 0) { + sb.append(COLUMN_LINE); + } + String header = r.get(i); + sb.append(SPACE); + sb.append(header); + sb.append(SPACE); + int l = header.length(); + int lw = columnCharNumber.get(i); + if (lw > l) { + for (int j = 0; j < (lw - l); j++) { + sb.append(SPACE); + } + } + sb.append(COLUMN_LINE); + } + sb.append(LF); + } + } - /** - * 拼装边框 - * - * @param sb StringBuilder - */ - private void fillBorder(StringBuilder sb) { - sb.append(CORNER); - for (Integer width : columnCharNumber) { - sb.append(Convert.toSBC(StrUtil.fillAfter("", ROW_LINE, width + 2))); - sb.append(CORNER); - } - sb.append(LF); - } + /** + * 拼装边框 + * + * @param sb StringBuilder + */ + private void fillBorder(StringBuilder sb) { + sb.append(CORNER); + for (Integer width : columnCharNumber) { + sb.append(Convert.toSBC(StrUtil.fillAfter("", ROW_LINE, width + 2))); + sb.append(CORNER); + } + sb.append(LF); + } - /** - * 打印到控制台 - */ - public void print() { - Console.print(toString()); - } + /** + * 打印到控制台 + */ + public void print() { + Console.print(toString()); + } } \ No newline at end of file From 9e2e9ee230af03179ca3aa20103be2a8c022a938 Mon Sep 17 00:00:00 2001 From: Looly Date: Wed, 30 Sep 2020 15:37:53 +0800 Subject: [PATCH 15/28] fix code --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a61cd285..7bbe45384 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ # 5.4.5 (2020-09-30) ### 新特性 +* 【core 】 ConsoleTable代码优化(pr#190@Gitee) ### Bug修复 From a62f2cd34a89e7fd1bb61847dd8591f0b66e4833 Mon Sep 17 00:00:00 2001 From: neko <52202080+akiyamaneko@users.noreply.github.com> Date: Wed, 30 Sep 2020 18:18:58 +0800 Subject: [PATCH 16/28] =?UTF-8?q?=E4=BC=98=E5=8C=96StrUtil?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/cn/hutool/core/util/StrUtil.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java index c4f1e686e..28717214f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java @@ -667,6 +667,9 @@ public class StrUtil { * @return 是否开始 */ public static boolean startWith(CharSequence str, char c) { + if(true == isEmpty(str)) { + return false; + } return c == str.charAt(0); } @@ -779,6 +782,9 @@ public class StrUtil { * @return 是否结尾 */ public static boolean endWith(CharSequence str, char c) { + if(true == isEmpty(str)) { + return false; + } return c == str.charAt(str.length() - 1); } @@ -1073,7 +1079,8 @@ public class StrUtil { * @return 移除后的字符串 */ public static String removeAll(CharSequence str, CharSequence strToRemove) { - if (isEmpty(str)) { + // strToRemove如果为空, 也不用继续后面的逻辑 + if (isEmpty(str) || isEmpty(strToRemove)) { return str(str); } return str.toString().replace(strToRemove, EMPTY); @@ -2125,7 +2132,6 @@ public class StrUtil { } final List result = new LinkedList<>(); - final String[] split = split(str, prefix); for (String fragment : split(str, prefix)) { int suffixIndex = fragment.indexOf(suffix.toString()); if (suffixIndex > 0) { @@ -2205,10 +2211,10 @@ public class StrUtil { if (null == str) { return null; } - if (count <= 0) { + if (count <= 0 || str.length() == 0) { return EMPTY; } - if (count == 1 || str.length() == 0) { + if (count == 1) { return str.toString(); } @@ -3997,11 +4003,12 @@ public class StrUtil { return false; } int len = value.length(); - boolean isAllMatch = true; for (int i = 0; i < len; i++) { - isAllMatch &= matcher.match(value.charAt(i)); + if(false == matcher.match(value.charAt(i))) { + return false; + } } - return isAllMatch; + return true; } /** From 050d3e6eac6330dac190ced97ef70873016e0554 Mon Sep 17 00:00:00 2001 From: neko <52202080+akiyamaneko@users.noreply.github.com> Date: Fri, 2 Oct 2020 10:57:55 +0800 Subject: [PATCH 17/28] =?UTF-8?q?=E7=AE=80=E5=8C=96=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/util/CreditCodeUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/CreditCodeUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/CreditCodeUtil.java index 557ccb3d4..0eb925da2 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/CreditCodeUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/CreditCodeUtil.java @@ -98,11 +98,11 @@ public class CreditCodeUtil { } for (int i = 2; i < 8; i++) { int num = RandomUtil.randomInt(10); - buf.append(Character.toUpperCase(BASE_CODE_ARRAY[num])); + buf.append(BASE_CODE_ARRAY[num]); } for (int i = 8; i < 17; i++) { int num = RandomUtil.randomInt(BASE_CODE_ARRAY.length - 1); - buf.append(Character.toUpperCase(BASE_CODE_ARRAY[num])); + buf.append(BASE_CODE_ARRAY[num]); } final String code = buf.toString(); From ede632714d571487190df1482e8498d1836cb95c Mon Sep 17 00:00:00 2001 From: neko <52202080+akiyamaneko@users.noreply.github.com> Date: Sat, 3 Oct 2020 17:12:09 +0800 Subject: [PATCH 18/28] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E6=BD=9C=E5=9C=A8?= =?UTF-8?q?=E7=9A=84overflow=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/cn/hutool/core/collection/ListUtil.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java index fef0bfac6..56814dd95 100644 --- a/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/collection/ListUtil.java @@ -252,8 +252,8 @@ public class ListUtil { return new ArrayList<>(0); } } - - if ((pageNo * pageSize) > resultSize) { + // 相乘可能会导致越界 临时用long + if (((long)pageNo * pageSize) > resultSize) { // 越界直接返回空 return new ArrayList<>(0); } From 2602935b60507532701b34c3b28a4939e4566f07 Mon Sep 17 00:00:00 2001 From: lixiaohua <1124205446@qq.com> Date: Thu, 8 Oct 2020 03:25:17 +0800 Subject: [PATCH 19/28] add method --- .../main/java/cn/hutool/core/util/XmlUtil.java | 17 +++++++++++++++++ .../java/cn/hutool/core/util/XmlUtilTest.java | 7 +++++++ 2 files changed, 24 insertions(+) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java index 357c859c7..09fbf6df8 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java @@ -69,6 +69,10 @@ public class XmlUtil { * 在XML中无效的字符 正则 */ public static final String INVALID_REGEX = "[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]"; + /** + * 在XML中注释的内容 正则 + */ + public static final String NOTE_REGEX = "(?s)"; /** * XML格式化输出默认缩进量 */ @@ -671,6 +675,19 @@ public class XmlUtil { return xmlContent.replaceAll(INVALID_REGEX, ""); } + /** + * 去除XML文本中的注释内容 + * + * @param xmlContent XML文本 + * @return 当传入为null时返回null + */ + public static String cleanNote(String xmlContent) { + if (xmlContent == null) { + return null; + } + return xmlContent.replaceAll(NOTE_REGEX, ""); + } + /** * 根据节点名获得子节点列表 * diff --git a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java index aaa9527ca..fb2a7e5c3 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java @@ -211,6 +211,13 @@ public class XmlUtilTest { Assert.assertEquals(testBean.getBankCode(), testBean2.getBankCode()); } + @Test + public void cleanNoteTest() { + final String xmlContent = "hutooljava"; + final String ret = XmlUtil.cleanNote(xmlContent); + Assert.assertEquals("hutooljava", ret); + } + @Data public static class TestBean { private String ReqCode; From ec2669d586154ff79ca90d59822f93ce39ca716a Mon Sep 17 00:00:00 2001 From: lixiaohua <1124205446@qq.com> Date: Thu, 8 Oct 2020 09:36:11 +0800 Subject: [PATCH 20/28] update unit test --- .../src/test/java/cn/hutool/core/util/XmlUtilTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java index fb2a7e5c3..a78c938da 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java @@ -213,9 +213,9 @@ public class XmlUtilTest { @Test public void cleanNoteTest() { - final String xmlContent = "hutooljava"; + final String xmlContent = "hutooljava"; final String ret = XmlUtil.cleanNote(xmlContent); - Assert.assertEquals("hutooljava", ret); + Assert.assertEquals("hutooljava", ret); } @Data From ecedb5fd8287743cabb85044e652122ebfec7812 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 9 Oct 2020 10:27:22 +0800 Subject: [PATCH 21/28] add method --- CHANGELOG.md | 4 +++- .../main/java/cn/hutool/core/util/XmlUtil.java | 7 ++++--- .../java/cn/hutool/core/util/XmlUtilTest.java | 4 ++-- .../src/main/java/cn/hutool/http/HttpRequest.java | 15 +++++++++++++++ 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bbe45384..80e55e771 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,10 +3,12 @@ ------------------------------------------------------------------------------------------------------------- -# 5.4.5 (2020-09-30) +# 5.4.5 (2020-10-09) ### 新特性 * 【core 】 ConsoleTable代码优化(pr#190@Gitee) +* 【http 】 HttpRequest增加setProxy重载(pr#190@Gitee) +* 【http 】 XmlUtil.cleanComment(pr#191@Gitee) ### Bug修复 diff --git a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java index 09fbf6df8..e7162eb4f 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/XmlUtil.java @@ -72,7 +72,7 @@ public class XmlUtil { /** * 在XML中注释的内容 正则 */ - public static final String NOTE_REGEX = "(?s)"; + public static final String COMMENT_REGEX = "(?s)"; /** * XML格式化输出默认缩进量 */ @@ -680,12 +680,13 @@ public class XmlUtil { * * @param xmlContent XML文本 * @return 当传入为null时返回null + * @since 5.4.5 */ - public static String cleanNote(String xmlContent) { + public static String cleanComment(String xmlContent) { if (xmlContent == null) { return null; } - return xmlContent.replaceAll(NOTE_REGEX, ""); + return xmlContent.replaceAll(COMMENT_REGEX, StrUtil.EMPTY); } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java index a78c938da..658d2440a 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/XmlUtilTest.java @@ -212,9 +212,9 @@ public class XmlUtilTest { } @Test - public void cleanNoteTest() { + public void cleanCommentTest() { final String xmlContent = "hutooljava"; - final String ret = XmlUtil.cleanNote(xmlContent); + final String ret = XmlUtil.cleanComment(xmlContent); Assert.assertEquals("hutooljava", ret); } diff --git a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java index 875805e21..b0cae62d8 100644 --- a/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java +++ b/hutool-http/src/main/java/cn/hutool/http/HttpRequest.java @@ -28,6 +28,7 @@ import java.io.OutputStream; import java.net.CookieManager; import java.net.HttpCookie; import java.net.HttpURLConnection; +import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URLStreamHandler; import java.util.Collection; @@ -841,6 +842,20 @@ public class HttpRequest extends HttpBase { return this; } + /** + * 设置Http代理 + * + * @param host 代理 主机 + * @param port 代理 端口 + * @return this + * @since 5.4.5 + */ + public HttpRequest setHttpProxy(String host, int port) { + final Proxy proxy = new Proxy(Proxy.Type.HTTP, + new InetSocketAddress(host, port)); + return setProxy(proxy); + } + /** * 设置代理 * From 308fa0f9db19306d63fd38dcaa01528620145546 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 9 Oct 2020 15:25:21 +0800 Subject: [PATCH 22/28] fix date bug --- CHANGELOG.md | 3 ++- .../java/cn/hutool/core/date/ChineseDate.java | 6 +++--- .../core/date/chinese/LunarFestival.java | 20 ++++++++++++++++++- .../cn/hutool/core/date/ChineseDateTest.java | 8 ++++++++ 4 files changed, 32 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 80e55e771..7e5bb6fd3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,9 +8,10 @@ ### 新特性 * 【core 】 ConsoleTable代码优化(pr#190@Gitee) * 【http 】 HttpRequest增加setProxy重载(pr#190@Gitee) -* 【http 】 XmlUtil.cleanComment(pr#191@Gitee) +* 【core 】 XmlUtil.cleanComment(pr#191@Gitee) ### Bug修复 +* 【core 】 解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee) ------------------------------------------------------------------------------------------------------------- diff --git a/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java b/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java index 735f35c2e..368cd302d 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/ChineseDate.java @@ -167,7 +167,7 @@ public class ChineseDate { * @return 是否为闰月 * @since 5.4.2 */ - public boolean isLeapMonth(){ + public boolean isLeapMonth() { return ChineseMonth.isLeapMonth(this.year, this.month); } @@ -230,7 +230,7 @@ public class ChineseDate { * @return 获得农历节日 */ public String getFestivals() { - return StrUtil.join(",", LunarFestival.getFestivals(this.month, this.day)); + return StrUtil.join(",", LunarFestival.getFestivals(this.year, this.month, day)); } /** @@ -258,7 +258,7 @@ public class ChineseDate { * @return 获得天干地支的年月日信息 */ public String getCyclicalYMD() { - if (gyear >= LunarInfo.BASE_YEAR && gmonth > 0 && gday > 0){ + if (gyear >= LunarInfo.BASE_YEAR && gmonth > 0 && gday > 0) { return (cyclicalm(gyear, gmonth, gday)); } return null; diff --git a/hutool-core/src/main/java/cn/hutool/core/date/chinese/LunarFestival.java b/hutool-core/src/main/java/cn/hutool/core/date/chinese/LunarFestival.java index 975302100..533c7365b 100644 --- a/hutool-core/src/main/java/cn/hutool/core/date/chinese/LunarFestival.java +++ b/hutool-core/src/main/java/cn/hutool/core/date/chinese/LunarFestival.java @@ -17,6 +17,7 @@ public class LunarFestival { // 来自:https://baike.baidu.com/item/%E4%B8%AD%E5%9B%BD%E4%BC%A0%E7%BB%9F%E8%8A%82%E6%97%A5/396100 private static final TableMap, String> L_FTV = new TableMap<>(16); static{ + // 节日 L_FTV.put(new Pair<>(1, 1), "春节"); L_FTV.put(new Pair<>(1, 2), "犬日"); L_FTV.put(new Pair<>(1, 3), "猪日"); @@ -78,7 +79,6 @@ public class LunarFestival { L_FTV.put(new Pair<>(12, 8), "腊八节"); L_FTV.put(new Pair<>(12, 16), "尾牙"); L_FTV.put(new Pair<>(12, 23), "小年"); - L_FTV.put(new Pair<>(12, 29), "除夕"); L_FTV.put(new Pair<>(12, 30), "除夕"); } @@ -88,6 +88,24 @@ public class LunarFestival { * @param month 月 * @param day 日 * @return 获得农历节日 + * @since 5.4.5 + */ + public static List getFestivals(int year, int month, int day) { + // 春节判断,如果12月是小月,则29为除夕,否则30为除夕 + if(12 == month && 29 == day){ + if(29 == LunarInfo.monthDays(year, month)){ + day++; + } + } + return getFestivals(month, day); + } + + /** + * 获得节日列表,此方法无法判断月是否为大月或小月 + * + * @param month 月 + * @param day 日 + * @return 获得农历节日 */ public static List getFestivals(int month, int day) { return L_FTV.getValues(new Pair<>(month, day)); diff --git a/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java b/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java index 53bd1dca6..877064d84 100644 --- a/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/date/ChineseDateTest.java @@ -1,5 +1,6 @@ package cn.hutool.core.date; +import cn.hutool.core.util.StrUtil; import org.junit.Assert; import org.junit.Test; @@ -77,4 +78,11 @@ public class ChineseDateTest { chineseDate = new ChineseDate(2020,4,15); Assert.assertEquals("闰四月", chineseDate.getChineseMonth()); } + + @Test + public void getFestivalsTest(){ + // issue#I1XHSF@Gitee,2023-01-20对应农历腊月29,非除夕 + ChineseDate chineseDate = new ChineseDate(DateUtil.parseDate("2023-01-20")); + Assert.assertTrue(StrUtil.isEmpty(chineseDate.getFestivals())); + } } From 7f83e35307eb3814f7380970afd3734d854d5531 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 9 Oct 2020 15:43:57 +0800 Subject: [PATCH 23/28] add test --- hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java index c6ccf2e85..1b1e2c28f 100644 --- a/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java +++ b/hutool-json/src/test/java/cn/hutool/json/JSONUtilTest.java @@ -154,4 +154,11 @@ public class JSONUtilTest { Assert.assertEquals("aa", json.get("name")); Assert.assertEquals(1, json.get("gender")); } + + @Test + public void doubleTest(){ + String json = "{\"test\": 12.00}"; + final JSONObject jsonObject = JSONUtil.parseObj(json); + Assert.assertEquals("12.00", jsonObject.getBigDecimal("test").setScale(2).toString()); + } } From 25e57bd4e934e3268bd5e17cbb680c8850894c4c Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 9 Oct 2020 15:54:51 +0800 Subject: [PATCH 24/28] fix bug --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e5bb6fd3..d6c936175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ ### Bug修复 * 【core 】 解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee) +* 【core 】 解决ListUtil计算总量可能的int溢出问题(pr#1150@Github) ------------------------------------------------------------------------------------------------------------- From 69362f103173bc5038da1da7eaa2bd53e6e5acbd Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 9 Oct 2020 16:01:25 +0800 Subject: [PATCH 25/28] add default value for ArrayUtil.unwrap --- CHANGELOG.md | 1 + .../src/main/java/cn/hutool/core/util/ArrayUtil.java | 8 ++++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6c936175..575659669 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * 【core 】 ConsoleTable代码优化(pr#190@Gitee) * 【http 】 HttpRequest增加setProxy重载(pr#190@Gitee) * 【core 】 XmlUtil.cleanComment(pr#191@Gitee) +* 【core 】 ArrayUtil.unWrap增加默认值(pr#1149@Github) ### Bug修复 * 【core 】 解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index a16f40b78..7157c0264 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -1777,7 +1777,7 @@ public class ArrayUtil { } /** - * 包装类数组转为原始类型数组 + * 包装类数组转为原始类型数组,null转为0 * * @param values 包装类型数组 * @return 原始类型数组 @@ -1793,7 +1793,7 @@ public class ArrayUtil { final int[] array = new int[length]; for (int i = 0; i < length; i++) { - array[i] = values[i]; + array[i] = ObjectUtil.defaultIfNull(values[i], 0); } return array; } @@ -1837,7 +1837,7 @@ public class ArrayUtil { final long[] array = new long[length]; for (int i = 0; i < length; i++) { - array[i] = values[i]; + array[i] = ObjectUtil.defaultIfNull(values[i], 0L); } return array; } @@ -1881,7 +1881,7 @@ public class ArrayUtil { char[] array = new char[length]; for (int i = 0; i < length; i++) { - array[i] = values[i]; + array[i] = ObjectUtil.defaultIfNull(values[i], Character.MIN_VALUE); } return array; } From c59acb3bac8584a8884377f1a62bfd78a0fffd9d Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 9 Oct 2020 16:30:19 +0800 Subject: [PATCH 26/28] fix equals --- CHANGELOG.md | 1 + .../java/cn/hutool/core/util/ArrayUtil.java | 8 ++++---- .../java/cn/hutool/core/util/NumberUtil.java | 18 ++++++++++++++++-- .../cn/hutool/core/util/NumberUtilTest.java | 10 +++++----- 4 files changed, 26 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 575659669..a625f9794 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ * 【http 】 HttpRequest增加setProxy重载(pr#190@Gitee) * 【core 】 XmlUtil.cleanComment(pr#191@Gitee) * 【core 】 ArrayUtil.unWrap增加默认值(pr#1149@Github) +* 【core 】 ArrayUtil.indexOf修改double的equals判断(pr#1147@Github) ### Bug修复 * 【core 】 解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index 7157c0264..c09dd1b87 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -1613,7 +1613,7 @@ public class ArrayUtil { public static int indexOf(double[] array, double value) { if (null != array) { for (int i = 0; i < array.length; i++) { - if (value == array[i]) { + if (NumberUtil.equals(value, array[i])) { return i; } } @@ -1632,7 +1632,7 @@ public class ArrayUtil { public static int lastIndexOf(double[] array, double value) { if (null != array) { for (int i = array.length - 1; i >= 0; i--) { - if (value == array[i]) { + if (NumberUtil.equals(value, array[i])) { return i; } } @@ -1663,7 +1663,7 @@ public class ArrayUtil { public static int indexOf(float[] array, float value) { if (null != array) { for (int i = 0; i < array.length; i++) { - if (value == array[i]) { + if (NumberUtil.equals(value, array[i])) { return i; } } @@ -1682,7 +1682,7 @@ public class ArrayUtil { public static int lastIndexOf(float[] array, float value) { if (null != array) { for (int i = array.length - 1; i >= 0; i--) { - if (value == array[i]) { + if (NumberUtil.equals(value, array[i])) { return i; } } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java index bb5e7af11..8465c0f29 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java @@ -1712,7 +1712,7 @@ public class NumberUtil { /** * 比较大小,值相等 返回true
- * 此方法通过调用{@link BigDecimal#compareTo(BigDecimal)}方法来判断是否相等
+ * 此方法通过调用{@link Double#doubleToLongBits(double)}方法来判断是否相等
* 此方法判断值相等时忽略精度的,即0.00 == 0 * * @param num1 数字1 @@ -1721,7 +1721,21 @@ public class NumberUtil { * @since 5.4.2 */ public static boolean equals(double num1, double num2) { - return equals(toBigDecimal(num1), toBigDecimal(num2)); + return Double.doubleToLongBits(num1) == Double.doubleToLongBits(num2); + } + + /** + * 比较大小,值相等 返回true
+ * 此方法通过调用{@link Double#doubleToLongBits(double)}方法来判断是否相等
+ * 此方法判断值相等时忽略精度的,即0.00 == 0 + * + * @param num1 数字1 + * @param num2 数字2 + * @return 是否相等 + * @since 5.4.5 + */ + public static boolean equals(float num1, float num2) { + return Float.floatToIntBits(num1) == Float.floatToIntBits(num2); } /** diff --git a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java index dd1710807..d0de97034 100644 --- a/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/NumberUtilTest.java @@ -263,10 +263,10 @@ public class NumberUtilTest { @Test public void isPowerOfTwoTest() { - Assert.assertEquals(false, NumberUtil.isPowerOfTwo(-1)); - Assert.assertEquals(true, NumberUtil.isPowerOfTwo(16)); - Assert.assertEquals(true, NumberUtil.isPowerOfTwo(65536)); - Assert.assertEquals(true, NumberUtil.isPowerOfTwo(1)); - Assert.assertEquals(false, NumberUtil.isPowerOfTwo(17)); + Assert.assertFalse(NumberUtil.isPowerOfTwo(-1)); + Assert.assertTrue(NumberUtil.isPowerOfTwo(16)); + Assert.assertTrue(NumberUtil.isPowerOfTwo(65536)); + Assert.assertTrue(NumberUtil.isPowerOfTwo(1)); + Assert.assertFalse(NumberUtil.isPowerOfTwo(17)); } } From 1a74642736402da6e7fa98ef39b5014bd212d0a3 Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 9 Oct 2020 16:48:12 +0800 Subject: [PATCH 27/28] enhance StrUtil --- CHANGELOG.md | 1 + .../java/cn/hutool/core/util/StrUtil.java | 171 +++++++++++++----- 2 files changed, 124 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a625f9794..0d03872d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * 【core 】 XmlUtil.cleanComment(pr#191@Gitee) * 【core 】 ArrayUtil.unWrap增加默认值(pr#1149@Github) * 【core 】 ArrayUtil.indexOf修改double的equals判断(pr#1147@Github) +* 【core 】 优化StrUtil中部分参数校验以及逻辑处理(pr#1144@Github) ### Bug修复 * 【core 】 解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee) diff --git a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java index 28717214f..51bac588c 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/StrUtil.java @@ -34,53 +34,95 @@ public class StrUtil { public static final int INDEX_NOT_FOUND = -1; - /** 字符常量:空格符 ' ' */ + /** + * 字符常量:空格符 ' ' + */ public static final char C_SPACE = CharUtil.SPACE; - /** 字符常量:制表符 \t */ + /** + * 字符常量:制表符 \t + */ public static final char C_TAB = CharUtil.TAB; - /** 字符常量:点 . */ + /** + * 字符常量:点 . + */ public static final char C_DOT = CharUtil.DOT; - /** 字符常量:斜杠 / */ + /** + * 字符常量:斜杠 / + */ public static final char C_SLASH = CharUtil.SLASH; - /** 字符常量:反斜杠 \ */ + /** + * 字符常量:反斜杠 \ + */ public static final char C_BACKSLASH = CharUtil.BACKSLASH; - /** 字符常量:回车符 \r */ + /** + * 字符常量:回车符 \r + */ public static final char C_CR = CharUtil.CR; - /** 字符常量:换行符 \n */ + /** + * 字符常量:换行符 \n + */ public static final char C_LF = CharUtil.LF; - /** 字符常量:下划线 _ */ + /** + * 字符常量:下划线 _ + */ public static final char C_UNDERLINE = CharUtil.UNDERLINE; - /** 字符常量:逗号 , */ + /** + * 字符常量:逗号 , + */ public static final char C_COMMA = CharUtil.COMMA; - /** 字符常量:花括号(左) { */ + /** + * 字符常量:花括号(左) { + */ public static final char C_DELIM_START = CharUtil.DELIM_START; - /** 字符常量:花括号(右) } */ + /** + * 字符常量:花括号(右) } + */ public static final char C_DELIM_END = CharUtil.DELIM_END; - /** 字符常量:中括号(左) [ */ + /** + * 字符常量:中括号(左) [ + */ public static final char C_BRACKET_START = CharUtil.BRACKET_START; - /** 字符常量:中括号(右) ] */ + /** + * 字符常量:中括号(右) ] + */ public static final char C_BRACKET_END = CharUtil.BRACKET_END; - /** 字符常量:冒号 : */ + /** + * 字符常量:冒号 : + */ public static final char C_COLON = CharUtil.COLON; - /** 字符常量:艾特 @ */ + /** + * 字符常量:艾特 @ + */ public static final char C_AT = CharUtil.AT; - /** 字符串常量:空格符 ' ' */ + /** + * 字符串常量:空格符 ' ' + */ public static final String SPACE = " "; - /** 字符串常量:制表符 \t */ + /** + * 字符串常量:制表符 \t + */ public static final String TAB = " "; - /** 字符串常量:点 . */ + /** + * 字符串常量:点 . + */ public static final String DOT = "."; /** * 字符串常量:双点 .. * 用途:作为指向上级文件夹的路径 "../path" */ public static final String DOUBLE_DOT = ".."; - /** 字符串常量:斜杠 / */ + /** + * 字符串常量:斜杠 / + */ public static final String SLASH = "/"; - /** 字符串常量:反斜杠 \ */ + /** + * 字符串常量:反斜杠 \ + */ public static final String BACKSLASH = "\\"; - /** 字符串常量:空字符串 "" */ + /** + * 字符串常量:空字符串 "" + */ public static final String EMPTY = ""; /** * 字符串常量:"null" @@ -92,45 +134,79 @@ public class StrUtil { * 解释:该字符常用于表示 Linux 系统和 MacOS 系统下的文本换行 */ public static final String CR = "\r"; - /** 字符串常量:换行符 \n */ + /** + * 字符串常量:换行符 \n + */ public static final String LF = "\n"; /** * 字符串常量:Windows 换行 \r\n * 解释:该字符串常用于表示 Windows 系统下的文本换行 */ public static final String CRLF = "\r\n"; - /** 字符串常量:下划线 _ */ + /** + * 字符串常量:下划线 _ + */ public static final String UNDERLINE = "_"; - /** 字符串常量:减号(中划线) - */ + /** + * 字符串常量:减号(中划线) - + */ public static final String DASHED = "-"; - /** 字符串常量:逗号 , */ + /** + * 字符串常量:逗号 , + */ public static final String COMMA = ","; - /** 字符串常量:花括号(左) { */ + /** + * 字符串常量:花括号(左) { + */ public static final String DELIM_START = "{"; - /** 字符串常量:花括号(右) } */ + /** + * 字符串常量:花括号(右) } + */ public static final String DELIM_END = "}"; - /** 字符串常量:中括号(左) [ */ + /** + * 字符串常量:中括号(左) [ + */ public static final String BRACKET_START = "["; - /** 字符串常量:中括号(右) ] */ + /** + * 字符串常量:中括号(右) ] + */ public static final String BRACKET_END = "]"; - /** 字符串常量:冒号 : */ + /** + * 字符串常量:冒号 : + */ public static final String COLON = ":"; - /** 字符串常量:艾特 @ */ + /** + * 字符串常量:艾特 @ + */ public static final String AT = "@"; - /** 字符串常量:HTML 空格转义 */ + /** + * 字符串常量:HTML 空格转义 + */ public static final String HTML_NBSP = " "; - /** 字符串常量:HTML And 符转义 & */ + /** + * 字符串常量:HTML And 符转义 & + */ public static final String HTML_AMP = "&"; - /** 字符串常量:HTML 双引号转义 " */ + /** + * 字符串常量:HTML 双引号转义 " + */ public static final String HTML_QUOTE = """; - /** 字符串常量:HTML 单引号转义 ' */ + /** + * 字符串常量:HTML 单引号转义 ' + */ public static final String HTML_APOS = "'"; - /** 字符串常量:HTML 小于号转义 < */ + /** + * 字符串常量:HTML 小于号转义 < + */ public static final String HTML_LT = "<"; - /** 字符串常量:HTML 大于号转义 > */ + /** + * 字符串常量:HTML 大于号转义 > + */ public static final String HTML_GT = ">"; - /** 字符串常量:空 JSON "{}" */ + /** + * 字符串常量:空 JSON "{}" + */ public static final String EMPTY_JSON = "{}"; // ------------------------------------------------------------------------ Blank @@ -189,8 +265,7 @@ public class StrUtil { * * @param obj 对象 * @return 如果为字符串是否为空串 - * - * @see StrUtil#isBlank(CharSequence) + * @see StrUtil#isBlank(CharSequence) * @since 3.3.0 */ public static boolean isBlankIfStr(Object obj) { @@ -667,7 +742,7 @@ public class StrUtil { * @return 是否开始 */ public static boolean startWith(CharSequence str, char c) { - if(true == isEmpty(str)) { + if (isEmpty(str)) { return false; } return c == str.charAt(0); @@ -677,8 +752,8 @@ public class StrUtil { * 是否以指定字符串开头
* 如果给定的字符串和开头字符串都为null则返回true,否则任意一个值为null返回false * - * @param str 被监测字符串 - * @param prefix 开头字符串 + * @param str 被监测字符串 + * @param prefix 开头字符串 * @param ignoreCase 是否忽略大小写 * @return 是否以指定字符串开头 * @since 5.4.3 @@ -693,14 +768,14 @@ public class StrUtil { * * @param str 被监测字符串 * @param prefix 开头字符串 - * @param ignoreCase 是否忽略大小写 + * @param ignoreCase 是否忽略大小写 * @param ignoreEquals 是否忽略字符串相等的情况 * @return 是否以指定字符串开头 * @since 5.4.3 */ public static boolean startWith(CharSequence str, CharSequence prefix, boolean ignoreCase, boolean ignoreEquals) { if (null == str || null == prefix) { - if(false == ignoreEquals){ + if (false == ignoreEquals) { return false; } return null == str && null == prefix; @@ -713,7 +788,7 @@ public class StrUtil { isStartWith = str.toString().startsWith(prefix.toString()); } - if(isStartWith){ + if (isStartWith) { return (false == ignoreEquals) || (false == equals(str, prefix, ignoreCase)); } return false; @@ -782,7 +857,7 @@ public class StrUtil { * @return 是否结尾 */ public static boolean endWith(CharSequence str, char c) { - if(true == isEmpty(str)) { + if (isEmpty(str)) { return false; } return c == str.charAt(str.length() - 1); @@ -4004,7 +4079,7 @@ public class StrUtil { } int len = value.length(); for (int i = 0; i < len; i++) { - if(false == matcher.match(value.charAt(i))) { + if (false == matcher.match(value.charAt(i))) { return false; } } From a341ad01986b46f23d1da6132b59ef74b078603e Mon Sep 17 00:00:00 2001 From: Looly Date: Fri, 9 Oct 2020 16:50:40 +0800 Subject: [PATCH 28/28] remove Character.toUpperCase --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d03872d2..db2dc718c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * 【core 】 ArrayUtil.unWrap增加默认值(pr#1149@Github) * 【core 】 ArrayUtil.indexOf修改double的equals判断(pr#1147@Github) * 【core 】 优化StrUtil中部分参数校验以及逻辑处理(pr#1144@Github) +* 【core 】 简化CreditCode逻辑去除无用Character.toUpperCase(pr#1145@Github) ### Bug修复 * 【core 】 解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee)