mirror of
https://gitee.com/chinabugotech/hutool.git
synced 2025-08-18 20:38:02 +08:00
Merge branch 'v5-dev' of https://github.com/totalo/hutool into v5-dev
This commit is contained in:
19
CHANGELOG.md
19
CHANGELOG.md
@@ -3,6 +3,23 @@
|
|||||||
|
|
||||||
-------------------------------------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# 5.4.5 (2020-10-09)
|
||||||
|
|
||||||
|
### 新特性
|
||||||
|
* 【core 】 ConsoleTable代码优化(pr#190@Gitee)
|
||||||
|
* 【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)
|
||||||
|
* 【core 】 优化StrUtil中部分参数校验以及逻辑处理(pr#1144@Github)
|
||||||
|
* 【core 】 简化CreditCode逻辑去除无用Character.toUpperCase(pr#1145@Github)
|
||||||
|
|
||||||
|
### Bug修复
|
||||||
|
* 【core 】 解决农历判断节日未判断大小月导致的问题(issue#I1XHSF@Gitee)
|
||||||
|
* 【core 】 解决ListUtil计算总量可能的int溢出问题(pr#1150@Github)
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
# 5.4.4 (2020-09-28)
|
# 5.4.4 (2020-09-28)
|
||||||
|
|
||||||
### 新特性
|
### 新特性
|
||||||
@@ -31,6 +48,8 @@
|
|||||||
* 【core 】 NumberUtil.factorial注释明确(pr#1126@Github)
|
* 【core 】 NumberUtil.factorial注释明确(pr#1126@Github)
|
||||||
* 【core 】 NumberUtil增加isPowerOfTwo方法(pr#1132@Github)
|
* 【core 】 NumberUtil增加isPowerOfTwo方法(pr#1132@Github)
|
||||||
* 【core 】 优化BooleanUtil的校验逻辑(pr#1137@Github)
|
* 【core 】 优化BooleanUtil的校验逻辑(pr#1137@Github)
|
||||||
|
* 【poi 】 改进sax方式读取逻辑,支持sheetId(issue#1141@Github)
|
||||||
|
* 【core 】 XmlUtil增加readBySax方法
|
||||||
|
|
||||||
### Bug修复
|
### Bug修复
|
||||||
* 【crypto 】 修复SM2验签后无法解密问题(issue#I1W0VP@Gitee)
|
* 【crypto 】 修复SM2验签后无法解密问题(issue#I1W0VP@Gitee)
|
||||||
|
|||||||
@@ -120,19 +120,19 @@ Each module can be introduced individually, or all modules can be introduced by
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.4.4</version>
|
<version>5.4.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Gradle
|
### Gradle
|
||||||
```
|
```
|
||||||
compile 'cn.hutool:hutool-all:5.4.4'
|
compile 'cn.hutool:hutool-all:5.4.5'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Download
|
## Download
|
||||||
|
|
||||||
- [Maven1](https://repo1.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.4/)
|
- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.5/)
|
||||||
|
|
||||||
> note:
|
> 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.
|
> Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available.
|
||||||
|
|||||||
20
README.md
20
README.md
@@ -119,21 +119,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不
|
|||||||
<dependency>
|
<dependency>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
<version>5.4.4</version>
|
<version>5.4.5</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Gradle
|
### Gradle
|
||||||
```
|
```
|
||||||
compile 'cn.hutool:hutool-all:5.4.4'
|
compile 'cn.hutool:hutool-all:5.4.5'
|
||||||
```
|
```
|
||||||
|
|
||||||
### 非Maven项目
|
### 非Maven项目
|
||||||
|
|
||||||
点击以下任一链接,下载`hutool-all-X.X.X.jar`即可:
|
点击以下任一链接,下载`hutool-all-X.X.X.jar`即可:
|
||||||
|
|
||||||
- [Maven中央库1](https://repo1.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.4/)
|
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.4.5/)
|
||||||
|
|
||||||
> 注意
|
> 注意
|
||||||
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。
|
> Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。
|
||||||
@@ -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
|
```sh
|
||||||
./hutool.sh install
|
./hutool.sh install
|
||||||
@@ -166,7 +166,7 @@ Hutool的源码分为两个分支,功能如下:
|
|||||||
|
|
||||||
提交问题反馈请说明正在使用的JDK版本呢、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)
|
- [Github issue](https://github.com/looly/hutool/issues)
|
||||||
|
|
||||||
|
|
||||||
@@ -177,14 +177,14 @@ Hutool的源码分为两个分支,功能如下:
|
|||||||
3. 修改代码(记得一定要修改v5-dev分支)
|
3. 修改代码(记得一定要修改v5-dev分支)
|
||||||
4. commit后push到自己的库(v5-dev分支)
|
4. commit后push到自己的库(v5-dev分支)
|
||||||
5. 登录Gitee或Github在你首页可以看到一个 pull request 按钮,点击它,填写一些说明信息,然后提交即可。
|
5. 登录Gitee或Github在你首页可以看到一个 pull request 按钮,点击它,填写一些说明信息,然后提交即可。
|
||||||
6. 等待作者合并
|
6. 等待维护者合并
|
||||||
|
|
||||||
### PR遵照的原则
|
### PR遵照的原则
|
||||||
|
|
||||||
Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过作者是一个强迫症患者,为了照顾病人,需要提交的pr(pull request)符合一些规范,规范如下:
|
Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过维护者是一个强迫症患者,为了照顾病人,需要提交的pr(pull request)符合一些规范,规范如下:
|
||||||
|
|
||||||
1. 注释完备,尤其每个新增的方法应按照Java文档规范标明方法说明、参数说明、返回值说明等信息,必要时请添加单元测试,如果愿意,也可以加上你的大名。
|
1. 注释完备,尤其每个新增的方法应按照Java文档规范标明方法说明、参数说明、返回值说明等信息,必要时请添加单元测试,如果愿意,也可以加上你的大名。
|
||||||
2. Hutool的缩进按照Eclipse(~~不要跟我说IDEA多好用,作者非常懒,学不会~~,IDEA真香,改了Eclipse快捷键后舒服多了)默认(tab)缩进,所以请遵守(不要和我争执空格与tab的问题,这是一个病人的习惯)。
|
2. Hutool的缩进按照Eclipse(~~不要跟我说IDEA多好用,维护者非常懒,学不会~~,IDEA真香,改了Eclipse快捷键后舒服多了)默认(tab)缩进,所以请遵守(不要和我争执空格与tab的问题,这是一个病人的习惯)。
|
||||||
3. 新加的方法不要使用第三方库的方法,Hutool遵循无依赖原则(除非在extra模块中加方法工具)。
|
3. 新加的方法不要使用第三方库的方法,Hutool遵循无依赖原则(除非在extra模块中加方法工具)。
|
||||||
4. 请pull request到`v5-dev`分支。Hutool在5.x版本后使用了新的分支:`v5-master`是主分支,表示已经发布中央库的版本,这个分支不允许pr,也不允许修改。
|
4. 请pull request到`v5-dev`分支。Hutool在5.x版本后使用了新的分支:`v5-master`是主分支,表示已经发布中央库的版本,这个分支不允许pr,也不允许修改。
|
||||||
|
|
||||||
@@ -192,7 +192,7 @@ Hutool欢迎任何人为Hutool添砖加瓦,贡献代码,不过作者是一
|
|||||||
|
|
||||||
## 捐赠
|
## 捐赠
|
||||||
|
|
||||||
如果你觉得Hutool不错,可以捐赠请作者吃包辣条~,在此表示感谢^_^。
|
如果你觉得Hutool不错,可以捐赠请维护者吃包辣条~,在此表示感谢^_^。
|
||||||
|
|
||||||
点击以下链接,将页面拉到最下方点击“捐赠”即可。
|
点击以下链接,将页面拉到最下方点击“捐赠”即可。
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
5.4.4
|
5.4.5
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
var version = '5.4.4'
|
var version = '5.4.5'
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-all</artifactId>
|
<artifactId>hutool-all</artifactId>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-aop</artifactId>
|
<artifactId>hutool-aop</artifactId>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-bloomFilter</artifactId>
|
<artifactId>hutool-bloomFilter</artifactId>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-bom</artifactId>
|
<artifactId>hutool-bom</artifactId>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-cache</artifactId>
|
<artifactId>hutool-cache</artifactId>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-captcha</artifactId>
|
<artifactId>hutool-captcha</artifactId>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-core</artifactId>
|
<artifactId>hutool-core</artifactId>
|
||||||
|
|||||||
@@ -252,8 +252,8 @@ public class ListUtil {
|
|||||||
return new ArrayList<>(0);
|
return new ArrayList<>(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 相乘可能会导致越界 临时用long
|
||||||
if ((pageNo * pageSize) > resultSize) {
|
if (((long)pageNo * pageSize) > resultSize) {
|
||||||
// 越界直接返回空
|
// 越界直接返回空
|
||||||
return new ArrayList<>(0);
|
return new ArrayList<>(0);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ public class ChineseDate {
|
|||||||
* @return 获得农历节日
|
* @return 获得农历节日
|
||||||
*/
|
*/
|
||||||
public String getFestivals() {
|
public String getFestivals() {
|
||||||
return StrUtil.join(",", LunarFestival.getFestivals(this.month, this.day));
|
return StrUtil.join(",", LunarFestival.getFestivals(this.year, this.month, day));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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
|
// 来自: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<Pair<Integer, Integer>, String> L_FTV = new TableMap<>(16);
|
private static final TableMap<Pair<Integer, Integer>, String> L_FTV = new TableMap<>(16);
|
||||||
static{
|
static{
|
||||||
|
// 节日
|
||||||
L_FTV.put(new Pair<>(1, 1), "春节");
|
L_FTV.put(new Pair<>(1, 1), "春节");
|
||||||
L_FTV.put(new Pair<>(1, 2), "犬日");
|
L_FTV.put(new Pair<>(1, 2), "犬日");
|
||||||
L_FTV.put(new Pair<>(1, 3), "猪日");
|
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, 8), "腊八节");
|
||||||
L_FTV.put(new Pair<>(12, 16), "尾牙");
|
L_FTV.put(new Pair<>(12, 16), "尾牙");
|
||||||
L_FTV.put(new Pair<>(12, 23), "小年");
|
L_FTV.put(new Pair<>(12, 23), "小年");
|
||||||
L_FTV.put(new Pair<>(12, 29), "除夕");
|
|
||||||
L_FTV.put(new Pair<>(12, 30), "除夕");
|
L_FTV.put(new Pair<>(12, 30), "除夕");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,6 +88,24 @@ public class LunarFestival {
|
|||||||
* @param month 月
|
* @param month 月
|
||||||
* @param day 日
|
* @param day 日
|
||||||
* @return 获得农历节日
|
* @return 获得农历节日
|
||||||
|
* @since 5.4.5
|
||||||
|
*/
|
||||||
|
public static List<String> 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<String> getFestivals(int month, int day) {
|
public static List<String> getFestivals(int month, int day) {
|
||||||
return L_FTV.getValues(new Pair<>(month, day));
|
return L_FTV.getValues(new Pair<>(month, day));
|
||||||
|
|||||||
151
hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java
Normal file
151
hutool-core/src/main/java/cn/hutool/core/lang/ConsoleTable.java
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
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;
|
||||||
|
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 static final char LF = CharUtil.LF;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 表格头信息
|
||||||
|
*/
|
||||||
|
private final List<List<String>> HEADER_LIST = new ArrayList<>();
|
||||||
|
/**
|
||||||
|
* 表格体信息
|
||||||
|
*/
|
||||||
|
private final List<List<String>> BODY_LIST = new ArrayList<>();
|
||||||
|
/**
|
||||||
|
* 每列最大字符个数
|
||||||
|
*/
|
||||||
|
private List<Integer> columnCharNumber;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加头信息
|
||||||
|
*
|
||||||
|
* @param titles 列名
|
||||||
|
* @return 自身对象
|
||||||
|
*/
|
||||||
|
public ConsoleTable addHeader(String... titles) {
|
||||||
|
if (columnCharNumber == null) {
|
||||||
|
columnCharNumber = new ArrayList<>(Collections.nCopies(titles.length, 0));
|
||||||
|
}
|
||||||
|
List<String> l = new ArrayList<>();
|
||||||
|
fillColumns(l, titles);
|
||||||
|
HEADER_LIST.add(l);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加体信息
|
||||||
|
*
|
||||||
|
* @param values 列值
|
||||||
|
* @return 自身对象
|
||||||
|
*/
|
||||||
|
public ConsoleTable addBody(String... values) {
|
||||||
|
List<String> l = new ArrayList<>();
|
||||||
|
BODY_LIST.add(l);
|
||||||
|
fillColumns(l, values);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 填充表格头或者体
|
||||||
|
*
|
||||||
|
* @param l 被填充列表
|
||||||
|
* @param columns 填充内容
|
||||||
|
*/
|
||||||
|
private void fillColumns(List<String> 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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 填充表头或者表体信息
|
||||||
|
*
|
||||||
|
* @param sb
|
||||||
|
* @param list 表头列表或者表体列表
|
||||||
|
*/
|
||||||
|
private void fillRow(StringBuilder sb, List<List<String>> list) {
|
||||||
|
for (List<String> 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 打印到控制台
|
||||||
|
*/
|
||||||
|
public void print() {
|
||||||
|
Console.print(toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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<List<String>> HEADER_LIST = new ArrayList<>();
|
|
||||||
/**
|
|
||||||
* 表格体信息
|
|
||||||
*/
|
|
||||||
private final List<List<String>> BODY_LIST = new ArrayList<>();
|
|
||||||
/**
|
|
||||||
* 每列最大字符个数
|
|
||||||
*/
|
|
||||||
private List<Integer> 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<String> l = new ArrayList<>();
|
|
||||||
HEADER_LIST.add(l);
|
|
||||||
fillColumns(l, titles);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 添加体信息
|
|
||||||
*
|
|
||||||
* @param values 列值
|
|
||||||
* @return 自身对象
|
|
||||||
*/
|
|
||||||
public ConsoleTableUtil addBody(String... values) {
|
|
||||||
List<String> l = new ArrayList<>();
|
|
||||||
BODY_LIST.add(l);
|
|
||||||
fillColumns(l, values);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 填充表格头或者体
|
|
||||||
*
|
|
||||||
* @param l
|
|
||||||
* @param columns
|
|
||||||
*/
|
|
||||||
private void fillColumns(List<String> 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<String> 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<String> 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());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1613,7 +1613,7 @@ public class ArrayUtil {
|
|||||||
public static int indexOf(double[] array, double value) {
|
public static int indexOf(double[] array, double value) {
|
||||||
if (null != array) {
|
if (null != array) {
|
||||||
for (int i = 0; i < array.length; i++) {
|
for (int i = 0; i < array.length; i++) {
|
||||||
if (value == array[i]) {
|
if (NumberUtil.equals(value, array[i])) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1632,7 +1632,7 @@ public class ArrayUtil {
|
|||||||
public static int lastIndexOf(double[] array, double value) {
|
public static int lastIndexOf(double[] array, double value) {
|
||||||
if (null != array) {
|
if (null != array) {
|
||||||
for (int i = array.length - 1; i >= 0; i--) {
|
for (int i = array.length - 1; i >= 0; i--) {
|
||||||
if (value == array[i]) {
|
if (NumberUtil.equals(value, array[i])) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1663,7 +1663,7 @@ public class ArrayUtil {
|
|||||||
public static int indexOf(float[] array, float value) {
|
public static int indexOf(float[] array, float value) {
|
||||||
if (null != array) {
|
if (null != array) {
|
||||||
for (int i = 0; i < array.length; i++) {
|
for (int i = 0; i < array.length; i++) {
|
||||||
if (value == array[i]) {
|
if (NumberUtil.equals(value, array[i])) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1682,7 +1682,7 @@ public class ArrayUtil {
|
|||||||
public static int lastIndexOf(float[] array, float value) {
|
public static int lastIndexOf(float[] array, float value) {
|
||||||
if (null != array) {
|
if (null != array) {
|
||||||
for (int i = array.length - 1; i >= 0; i--) {
|
for (int i = array.length - 1; i >= 0; i--) {
|
||||||
if (value == array[i]) {
|
if (NumberUtil.equals(value, array[i])) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1777,7 +1777,7 @@ public class ArrayUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 包装类数组转为原始类型数组
|
* 包装类数组转为原始类型数组,null转为0
|
||||||
*
|
*
|
||||||
* @param values 包装类型数组
|
* @param values 包装类型数组
|
||||||
* @return 原始类型数组
|
* @return 原始类型数组
|
||||||
@@ -1793,7 +1793,7 @@ public class ArrayUtil {
|
|||||||
|
|
||||||
final int[] array = new int[length];
|
final int[] array = new int[length];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
array[i] = values[i];
|
array[i] = ObjectUtil.defaultIfNull(values[i], 0);
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
@@ -1837,7 +1837,7 @@ public class ArrayUtil {
|
|||||||
|
|
||||||
final long[] array = new long[length];
|
final long[] array = new long[length];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
array[i] = values[i];
|
array[i] = ObjectUtil.defaultIfNull(values[i], 0L);
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
@@ -1881,7 +1881,7 @@ public class ArrayUtil {
|
|||||||
|
|
||||||
char[] array = new char[length];
|
char[] array = new char[length];
|
||||||
for (int i = 0; i < length; i++) {
|
for (int i = 0; i < length; i++) {
|
||||||
array[i] = values[i];
|
array[i] = ObjectUtil.defaultIfNull(values[i], Character.MIN_VALUE);
|
||||||
}
|
}
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,11 +98,11 @@ public class CreditCodeUtil {
|
|||||||
}
|
}
|
||||||
for (int i = 2; i < 8; i++) {
|
for (int i = 2; i < 8; i++) {
|
||||||
int num = RandomUtil.randomInt(10);
|
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++) {
|
for (int i = 8; i < 17; i++) {
|
||||||
int num = RandomUtil.randomInt(BASE_CODE_ARRAY.length - 1);
|
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();
|
final String code = buf.toString();
|
||||||
|
|||||||
@@ -1712,7 +1712,7 @@ public class NumberUtil {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 比较大小,值相等 返回true<br>
|
* 比较大小,值相等 返回true<br>
|
||||||
* 此方法通过调用{@link BigDecimal#compareTo(BigDecimal)}方法来判断是否相等<br>
|
* 此方法通过调用{@link Double#doubleToLongBits(double)}方法来判断是否相等<br>
|
||||||
* 此方法判断值相等时忽略精度的,即0.00 == 0
|
* 此方法判断值相等时忽略精度的,即0.00 == 0
|
||||||
*
|
*
|
||||||
* @param num1 数字1
|
* @param num1 数字1
|
||||||
@@ -1721,7 +1721,21 @@ public class NumberUtil {
|
|||||||
* @since 5.4.2
|
* @since 5.4.2
|
||||||
*/
|
*/
|
||||||
public static boolean equals(double num1, double num2) {
|
public static boolean equals(double num1, double num2) {
|
||||||
return equals(toBigDecimal(num1), toBigDecimal(num2));
|
return Double.doubleToLongBits(num1) == Double.doubleToLongBits(num2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 比较大小,值相等 返回true<br>
|
||||||
|
* 此方法通过调用{@link Double#doubleToLongBits(double)}方法来判断是否相等<br>
|
||||||
|
* 此方法判断值相等时忽略精度的,即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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -522,8 +522,9 @@ public class RandomUtil {
|
|||||||
*
|
*
|
||||||
* @return 随机颜色
|
* @return 随机颜色
|
||||||
* @since 4.1.5
|
* @since 4.1.5
|
||||||
* @deprecated 使用{@link ImagUtil#randomColor()}
|
* @deprecated 使用ImgUtil.randomColor()
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static Color randomColor() {
|
public static Color randomColor() {
|
||||||
final Random random = getRandom();
|
final Random random = getRandom();
|
||||||
return new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
|
return new Color(random.nextInt(256), random.nextInt(256), random.nextInt(256));
|
||||||
|
|||||||
@@ -34,53 +34,95 @@ public class StrUtil {
|
|||||||
|
|
||||||
public static final int INDEX_NOT_FOUND = -1;
|
public static final int INDEX_NOT_FOUND = -1;
|
||||||
|
|
||||||
/** 字符常量:空格符 ' ' */
|
/**
|
||||||
|
* 字符常量:空格符 ' '
|
||||||
|
*/
|
||||||
public static final char C_SPACE = CharUtil.SPACE;
|
public static final char C_SPACE = CharUtil.SPACE;
|
||||||
/** 字符常量:制表符 \t */
|
/**
|
||||||
|
* 字符常量:制表符 \t
|
||||||
|
*/
|
||||||
public static final char C_TAB = CharUtil.TAB;
|
public static final char C_TAB = CharUtil.TAB;
|
||||||
/** 字符常量:点 . */
|
/**
|
||||||
|
* 字符常量:点 .
|
||||||
|
*/
|
||||||
public static final char C_DOT = CharUtil.DOT;
|
public static final char C_DOT = CharUtil.DOT;
|
||||||
/** 字符常量:斜杠 / */
|
/**
|
||||||
|
* 字符常量:斜杠 /
|
||||||
|
*/
|
||||||
public static final char C_SLASH = CharUtil.SLASH;
|
public static final char C_SLASH = CharUtil.SLASH;
|
||||||
/** 字符常量:反斜杠 \ */
|
/**
|
||||||
|
* 字符常量:反斜杠 \
|
||||||
|
*/
|
||||||
public static final char C_BACKSLASH = CharUtil.BACKSLASH;
|
public static final char C_BACKSLASH = CharUtil.BACKSLASH;
|
||||||
/** 字符常量:回车符 \r */
|
/**
|
||||||
|
* 字符常量:回车符 \r
|
||||||
|
*/
|
||||||
public static final char C_CR = CharUtil.CR;
|
public static final char C_CR = CharUtil.CR;
|
||||||
/** 字符常量:换行符 \n */
|
/**
|
||||||
|
* 字符常量:换行符 \n
|
||||||
|
*/
|
||||||
public static final char C_LF = CharUtil.LF;
|
public static final char C_LF = CharUtil.LF;
|
||||||
/** 字符常量:下划线 _ */
|
/**
|
||||||
|
* 字符常量:下划线 _
|
||||||
|
*/
|
||||||
public static final char C_UNDERLINE = CharUtil.UNDERLINE;
|
public static final char C_UNDERLINE = CharUtil.UNDERLINE;
|
||||||
/** 字符常量:逗号 , */
|
/**
|
||||||
|
* 字符常量:逗号 ,
|
||||||
|
*/
|
||||||
public static final char C_COMMA = CharUtil.COMMA;
|
public static final char C_COMMA = CharUtil.COMMA;
|
||||||
/** 字符常量:花括号(左) { */
|
/**
|
||||||
|
* 字符常量:花括号(左) {
|
||||||
|
*/
|
||||||
public static final char C_DELIM_START = CharUtil.DELIM_START;
|
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_DELIM_END = CharUtil.DELIM_END;
|
||||||
/** 字符常量:中括号(左) [ */
|
/**
|
||||||
|
* 字符常量:中括号(左) [
|
||||||
|
*/
|
||||||
public static final char C_BRACKET_START = CharUtil.BRACKET_START;
|
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_BRACKET_END = CharUtil.BRACKET_END;
|
||||||
/** 字符常量:冒号 : */
|
/**
|
||||||
|
* 字符常量:冒号 :
|
||||||
|
*/
|
||||||
public static final char C_COLON = CharUtil.COLON;
|
public static final char C_COLON = CharUtil.COLON;
|
||||||
/** 字符常量:艾特 @ */
|
/**
|
||||||
|
* 字符常量:艾特 @
|
||||||
|
*/
|
||||||
public static final char C_AT = CharUtil.AT;
|
public static final char C_AT = CharUtil.AT;
|
||||||
|
|
||||||
/** 字符串常量:空格符 ' ' */
|
/**
|
||||||
|
* 字符串常量:空格符 ' '
|
||||||
|
*/
|
||||||
public static final String SPACE = " ";
|
public static final String SPACE = " ";
|
||||||
/** 字符串常量:制表符 \t */
|
/**
|
||||||
|
* 字符串常量:制表符 \t
|
||||||
|
*/
|
||||||
public static final String TAB = " ";
|
public static final String TAB = " ";
|
||||||
/** 字符串常量:点 . */
|
/**
|
||||||
|
* 字符串常量:点 .
|
||||||
|
*/
|
||||||
public static final String DOT = ".";
|
public static final String DOT = ".";
|
||||||
/**
|
/**
|
||||||
* 字符串常量:双点 ..
|
* 字符串常量:双点 ..
|
||||||
* 用途:作为指向上级文件夹的路径 "../path"
|
* 用途:作为指向上级文件夹的路径 "../path"
|
||||||
*/
|
*/
|
||||||
public static final String DOUBLE_DOT = "..";
|
public static final String DOUBLE_DOT = "..";
|
||||||
/** 字符串常量:斜杠 / */
|
/**
|
||||||
|
* 字符串常量:斜杠 /
|
||||||
|
*/
|
||||||
public static final String SLASH = "/";
|
public static final String SLASH = "/";
|
||||||
/** 字符串常量:反斜杠 \ */
|
/**
|
||||||
|
* 字符串常量:反斜杠 \
|
||||||
|
*/
|
||||||
public static final String BACKSLASH = "\\";
|
public static final String BACKSLASH = "\\";
|
||||||
/** 字符串常量:空字符串 "" */
|
/**
|
||||||
|
* 字符串常量:空字符串 ""
|
||||||
|
*/
|
||||||
public static final String EMPTY = "";
|
public static final String EMPTY = "";
|
||||||
/**
|
/**
|
||||||
* 字符串常量:"null"
|
* 字符串常量:"null"
|
||||||
@@ -92,45 +134,79 @@ public class StrUtil {
|
|||||||
* 解释:该字符常用于表示 Linux 系统和 MacOS 系统下的文本换行
|
* 解释:该字符常用于表示 Linux 系统和 MacOS 系统下的文本换行
|
||||||
*/
|
*/
|
||||||
public static final String CR = "\r";
|
public static final String CR = "\r";
|
||||||
/** 字符串常量:换行符 \n */
|
/**
|
||||||
|
* 字符串常量:换行符 \n
|
||||||
|
*/
|
||||||
public static final String LF = "\n";
|
public static final String LF = "\n";
|
||||||
/**
|
/**
|
||||||
* 字符串常量:Windows 换行 \r\n
|
* 字符串常量:Windows 换行 \r\n
|
||||||
* 解释:该字符串常用于表示 Windows 系统下的文本换行
|
* 解释:该字符串常用于表示 Windows 系统下的文本换行
|
||||||
*/
|
*/
|
||||||
public static final String CRLF = "\r\n";
|
public static final String CRLF = "\r\n";
|
||||||
/** 字符串常量:下划线 _ */
|
/**
|
||||||
|
* 字符串常量:下划线 _
|
||||||
|
*/
|
||||||
public static final String UNDERLINE = "_";
|
public static final String UNDERLINE = "_";
|
||||||
/** 字符串常量:减号(中划线) - */
|
/**
|
||||||
|
* 字符串常量:减号(中划线) -
|
||||||
|
*/
|
||||||
public static final String DASHED = "-";
|
public static final String DASHED = "-";
|
||||||
/** 字符串常量:逗号 , */
|
/**
|
||||||
|
* 字符串常量:逗号 ,
|
||||||
|
*/
|
||||||
public static final String COMMA = ",";
|
public static final String COMMA = ",";
|
||||||
/** 字符串常量:花括号(左) { */
|
/**
|
||||||
|
* 字符串常量:花括号(左) {
|
||||||
|
*/
|
||||||
public static final String DELIM_START = "{";
|
public static final String DELIM_START = "{";
|
||||||
/** 字符串常量:花括号(右) } */
|
/**
|
||||||
|
* 字符串常量:花括号(右) }
|
||||||
|
*/
|
||||||
public static final String DELIM_END = "}";
|
public static final String DELIM_END = "}";
|
||||||
/** 字符串常量:中括号(左) [ */
|
/**
|
||||||
|
* 字符串常量:中括号(左) [
|
||||||
|
*/
|
||||||
public static final String BRACKET_START = "[";
|
public static final String BRACKET_START = "[";
|
||||||
/** 字符串常量:中括号(右) ] */
|
/**
|
||||||
|
* 字符串常量:中括号(右) ]
|
||||||
|
*/
|
||||||
public static final String BRACKET_END = "]";
|
public static final String BRACKET_END = "]";
|
||||||
/** 字符串常量:冒号 : */
|
/**
|
||||||
|
* 字符串常量:冒号 :
|
||||||
|
*/
|
||||||
public static final String COLON = ":";
|
public static final String COLON = ":";
|
||||||
/** 字符串常量:艾特 @ */
|
/**
|
||||||
|
* 字符串常量:艾特 @
|
||||||
|
*/
|
||||||
public static final String AT = "@";
|
public static final String AT = "@";
|
||||||
|
|
||||||
/** 字符串常量:HTML 空格转义 */
|
/**
|
||||||
|
* 字符串常量:HTML 空格转义
|
||||||
|
*/
|
||||||
public static final String HTML_NBSP = " ";
|
public static final String HTML_NBSP = " ";
|
||||||
/** 字符串常量:HTML And 符转义 & */
|
/**
|
||||||
|
* 字符串常量:HTML And 符转义 &
|
||||||
|
*/
|
||||||
public static final String HTML_AMP = "&";
|
public static final String HTML_AMP = "&";
|
||||||
/** 字符串常量:HTML 双引号转义 " */
|
/**
|
||||||
|
* 字符串常量:HTML 双引号转义 "
|
||||||
|
*/
|
||||||
public static final String HTML_QUOTE = """;
|
public static final String HTML_QUOTE = """;
|
||||||
/** 字符串常量:HTML 单引号转义 ' */
|
/**
|
||||||
|
* 字符串常量:HTML 单引号转义 '
|
||||||
|
*/
|
||||||
public static final String HTML_APOS = "'";
|
public static final String HTML_APOS = "'";
|
||||||
/** 字符串常量:HTML 小于号转义 < */
|
/**
|
||||||
|
* 字符串常量:HTML 小于号转义 <
|
||||||
|
*/
|
||||||
public static final String HTML_LT = "<";
|
public static final String HTML_LT = "<";
|
||||||
/** 字符串常量:HTML 大于号转义 > */
|
/**
|
||||||
|
* 字符串常量:HTML 大于号转义 >
|
||||||
|
*/
|
||||||
public static final String HTML_GT = ">";
|
public static final String HTML_GT = ">";
|
||||||
/** 字符串常量:空 JSON "{}" */
|
/**
|
||||||
|
* 字符串常量:空 JSON "{}"
|
||||||
|
*/
|
||||||
public static final String EMPTY_JSON = "{}";
|
public static final String EMPTY_JSON = "{}";
|
||||||
|
|
||||||
// ------------------------------------------------------------------------ Blank
|
// ------------------------------------------------------------------------ Blank
|
||||||
@@ -189,7 +265,6 @@ public class StrUtil {
|
|||||||
*
|
*
|
||||||
* @param obj 对象
|
* @param obj 对象
|
||||||
* @return 如果为字符串是否为空串
|
* @return 如果为字符串是否为空串
|
||||||
*
|
|
||||||
* @see StrUtil#isBlank(CharSequence)
|
* @see StrUtil#isBlank(CharSequence)
|
||||||
* @since 3.3.0
|
* @since 3.3.0
|
||||||
*/
|
*/
|
||||||
@@ -667,6 +742,9 @@ public class StrUtil {
|
|||||||
* @return 是否开始
|
* @return 是否开始
|
||||||
*/
|
*/
|
||||||
public static boolean startWith(CharSequence str, char c) {
|
public static boolean startWith(CharSequence str, char c) {
|
||||||
|
if (isEmpty(str)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return c == str.charAt(0);
|
return c == str.charAt(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -779,6 +857,9 @@ public class StrUtil {
|
|||||||
* @return 是否结尾
|
* @return 是否结尾
|
||||||
*/
|
*/
|
||||||
public static boolean endWith(CharSequence str, char c) {
|
public static boolean endWith(CharSequence str, char c) {
|
||||||
|
if (isEmpty(str)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return c == str.charAt(str.length() - 1);
|
return c == str.charAt(str.length() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1073,7 +1154,8 @@ public class StrUtil {
|
|||||||
* @return 移除后的字符串
|
* @return 移除后的字符串
|
||||||
*/
|
*/
|
||||||
public static String removeAll(CharSequence str, CharSequence strToRemove) {
|
public static String removeAll(CharSequence str, CharSequence strToRemove) {
|
||||||
if (isEmpty(str)) {
|
// strToRemove如果为空, 也不用继续后面的逻辑
|
||||||
|
if (isEmpty(str) || isEmpty(strToRemove)) {
|
||||||
return str(str);
|
return str(str);
|
||||||
}
|
}
|
||||||
return str.toString().replace(strToRemove, EMPTY);
|
return str.toString().replace(strToRemove, EMPTY);
|
||||||
@@ -2125,7 +2207,6 @@ public class StrUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final List<String> result = new LinkedList<>();
|
final List<String> result = new LinkedList<>();
|
||||||
final String[] split = split(str, prefix);
|
|
||||||
for (String fragment : split(str, prefix)) {
|
for (String fragment : split(str, prefix)) {
|
||||||
int suffixIndex = fragment.indexOf(suffix.toString());
|
int suffixIndex = fragment.indexOf(suffix.toString());
|
||||||
if (suffixIndex > 0) {
|
if (suffixIndex > 0) {
|
||||||
@@ -2205,10 +2286,10 @@ public class StrUtil {
|
|||||||
if (null == str) {
|
if (null == str) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (count <= 0) {
|
if (count <= 0 || str.length() == 0) {
|
||||||
return EMPTY;
|
return EMPTY;
|
||||||
}
|
}
|
||||||
if (count == 1 || str.length() == 0) {
|
if (count == 1) {
|
||||||
return str.toString();
|
return str.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3997,11 +4078,12 @@ public class StrUtil {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
int len = value.length();
|
int len = value.length();
|
||||||
boolean isAllMatch = true;
|
|
||||||
for (int i = 0; i < len; i++) {
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
|
|||||||
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.exceptions.UtilException;
|
import cn.hutool.core.exceptions.UtilException;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.lang.Assert;
|
import cn.hutool.core.lang.Assert;
|
||||||
import cn.hutool.core.map.BiMap;
|
import cn.hutool.core.map.BiMap;
|
||||||
@@ -13,7 +14,11 @@ import org.w3c.dom.Element;
|
|||||||
import org.w3c.dom.NamedNodeMap;
|
import org.w3c.dom.NamedNodeMap;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.w3c.dom.NodeList;
|
import org.w3c.dom.NodeList;
|
||||||
|
import org.xml.sax.ContentHandler;
|
||||||
import org.xml.sax.InputSource;
|
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.XMLConstants;
|
||||||
import javax.xml.namespace.NamespaceContext;
|
import javax.xml.namespace.NamespaceContext;
|
||||||
@@ -21,6 +26,8 @@ import javax.xml.namespace.QName;
|
|||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import javax.xml.parsers.DocumentBuilderFactory;
|
import javax.xml.parsers.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.ParserConfigurationException;
|
import javax.xml.parsers.ParserConfigurationException;
|
||||||
|
import javax.xml.parsers.SAXParser;
|
||||||
|
import javax.xml.parsers.SAXParserFactory;
|
||||||
import javax.xml.transform.OutputKeys;
|
import javax.xml.transform.OutputKeys;
|
||||||
import javax.xml.transform.Result;
|
import javax.xml.transform.Result;
|
||||||
import javax.xml.transform.Source;
|
import javax.xml.transform.Source;
|
||||||
@@ -62,6 +69,10 @@ public class XmlUtil {
|
|||||||
* 在XML中无效的字符 正则
|
* 在XML中无效的字符 正则
|
||||||
*/
|
*/
|
||||||
public static final String INVALID_REGEX = "[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]";
|
public static final String INVALID_REGEX = "[\\x00-\\x08\\x0b-\\x0c\\x0e-\\x1f]";
|
||||||
|
/**
|
||||||
|
* 在XML中注释的内容 正则
|
||||||
|
*/
|
||||||
|
public static final String COMMENT_REGEX = "(?s)<!--.+?-->";
|
||||||
/**
|
/**
|
||||||
* XML格式化输出默认缩进量
|
* XML格式化输出默认缩进量
|
||||||
*/
|
*/
|
||||||
@@ -76,6 +87,10 @@ public class XmlUtil {
|
|||||||
* 是否打开命名空间支持
|
* 是否打开命名空间支持
|
||||||
*/
|
*/
|
||||||
private static boolean namespaceAware = true;
|
private static boolean namespaceAware = true;
|
||||||
|
/**
|
||||||
|
* Sax读取器工厂缓存
|
||||||
|
*/
|
||||||
|
private static SAXParserFactory factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 禁用默认的DocumentBuilderFactory,禁用后如果有第三方的实现(如oracle的xdb包中的xmlparse),将会自动加载实现。
|
* 禁用默认的DocumentBuilderFactory,禁用后如果有第三方的实现(如oracle的xdb包中的xmlparse),将会自动加载实现。
|
||||||
@@ -184,6 +199,92 @@ public class XmlUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用Sax方式读取指定的XML<br>
|
||||||
|
* 如果用户传入的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<br>
|
||||||
|
* 如果用户传入的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<br>
|
||||||
|
* 如果用户传入的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<br>
|
||||||
|
* 如果用户传入的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文档
|
* 将String类型的XML转换为XML文档
|
||||||
*
|
*
|
||||||
@@ -574,6 +675,20 @@ public class XmlUtil {
|
|||||||
return xmlContent.replaceAll(INVALID_REGEX, "");
|
return xmlContent.replaceAll(INVALID_REGEX, "");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 去除XML文本中的注释内容
|
||||||
|
*
|
||||||
|
* @param xmlContent XML文本
|
||||||
|
* @return 当传入为null时返回null
|
||||||
|
* @since 5.4.5
|
||||||
|
*/
|
||||||
|
public static String cleanComment(String xmlContent) {
|
||||||
|
if (xmlContent == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return xmlContent.replaceAll(COMMENT_REGEX, StrUtil.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据节点名获得子节点列表
|
* 根据节点名获得子节点列表
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package cn.hutool.core.date;
|
package cn.hutool.core.date;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@@ -77,4 +78,11 @@ public class ChineseDateTest {
|
|||||||
chineseDate = new ChineseDate(2020,4,15);
|
chineseDate = new ChineseDate(2020,4,15);
|
||||||
Assert.assertEquals("闰四月", chineseDate.getChineseMonth());
|
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()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ public class ImgUtilTest {
|
|||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
public void scaleTest2() {
|
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
|
@Test
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
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();
|
||||||
|
|
||||||
|
Console.log();
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -263,10 +263,10 @@ public class NumberUtilTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void isPowerOfTwoTest() {
|
public void isPowerOfTwoTest() {
|
||||||
Assert.assertEquals(false, NumberUtil.isPowerOfTwo(-1));
|
Assert.assertFalse(NumberUtil.isPowerOfTwo(-1));
|
||||||
Assert.assertEquals(true, NumberUtil.isPowerOfTwo(16));
|
Assert.assertTrue(NumberUtil.isPowerOfTwo(16));
|
||||||
Assert.assertEquals(true, NumberUtil.isPowerOfTwo(65536));
|
Assert.assertTrue(NumberUtil.isPowerOfTwo(65536));
|
||||||
Assert.assertEquals(true, NumberUtil.isPowerOfTwo(1));
|
Assert.assertTrue(NumberUtil.isPowerOfTwo(1));
|
||||||
Assert.assertEquals(false, NumberUtil.isPowerOfTwo(17));
|
Assert.assertFalse(NumberUtil.isPowerOfTwo(17));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,13 @@ import org.junit.Assert;
|
|||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
|
import org.xml.sax.Attributes;
|
||||||
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
|
|
||||||
import javax.xml.xpath.XPathConstants;
|
import javax.xml.xpath.XPathConstants;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link XmlUtil} 工具类
|
* {@link XmlUtil} 工具类
|
||||||
@@ -148,6 +151,18 @@ public class XmlUtilTest {
|
|||||||
Assert.assertNotNull(doc);
|
Assert.assertNotNull(doc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void readBySaxTest(){
|
||||||
|
final Set<String> 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
|
@Test
|
||||||
public void mapToXmlTestWithOmitXmlDeclaration() {
|
public void mapToXmlTestWithOmitXmlDeclaration() {
|
||||||
|
|
||||||
@@ -196,6 +211,13 @@ public class XmlUtilTest {
|
|||||||
Assert.assertEquals(testBean.getBankCode(), testBean2.getBankCode());
|
Assert.assertEquals(testBean.getBankCode(), testBean2.getBankCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void cleanCommentTest() {
|
||||||
|
final String xmlContent = "<info><title>hutool</title><!-- 这是注释 --><lang>java</lang></info>";
|
||||||
|
final String ret = XmlUtil.cleanComment(xmlContent);
|
||||||
|
Assert.assertEquals("<info><title>hutool</title><lang>java</lang></info>", ret);
|
||||||
|
}
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public static class TestBean {
|
public static class TestBean {
|
||||||
private String ReqCode;
|
private String ReqCode;
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-cron</artifactId>
|
<artifactId>hutool-cron</artifactId>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-crypto</artifactId>
|
<artifactId>hutool-crypto</artifactId>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-db</artifactId>
|
<artifactId>hutool-db</artifactId>
|
||||||
@@ -19,9 +19,9 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<!-- versions -->
|
<!-- versions -->
|
||||||
<c3p0.version>0.9.5.5</c3p0.version>
|
<c3p0.version>0.9.5.5</c3p0.version>
|
||||||
<dbcp2.version>2.7.0</dbcp2.version>
|
<dbcp2.version>2.8.0</dbcp2.version>
|
||||||
<tomcat-jdbc.version>9.0.30</tomcat-jdbc.version>
|
<tomcat-jdbc.version>9.0.30</tomcat-jdbc.version>
|
||||||
<druid.version>1.1.23</druid.version>
|
<druid.version>1.1.24</druid.version>
|
||||||
<hikariCP.version>2.4.13</hikariCP.version>
|
<hikariCP.version>2.4.13</hikariCP.version>
|
||||||
<mongo.version>3.12.7</mongo.version>
|
<mongo.version>3.12.7</mongo.version>
|
||||||
<sqlite.version>3.32.3.2</sqlite.version>
|
<sqlite.version>3.32.3.2</sqlite.version>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-dfa</artifactId>
|
<artifactId>hutool-dfa</artifactId>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-extra</artifactId>
|
<artifactId>hutool-extra</artifactId>
|
||||||
@@ -19,15 +19,15 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<!-- versions -->
|
<!-- versions -->
|
||||||
<velocity.version>2.2</velocity.version>
|
<velocity.version>2.2</velocity.version>
|
||||||
<beetl.version>3.2.0.RELEASE</beetl.version>
|
<beetl.version>3.2.1.RELEASE</beetl.version>
|
||||||
<rythm.version>1.3.0</rythm.version>
|
<rythm.version>1.3.0</rythm.version>
|
||||||
<freemarker.version>2.3.30</freemarker.version>
|
<freemarker.version>2.3.30</freemarker.version>
|
||||||
<enjoy.version>4.9.01</enjoy.version>
|
<enjoy.version>4.9.01</enjoy.version>
|
||||||
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
|
<thymeleaf.version>3.0.11.RELEASE</thymeleaf.version>
|
||||||
<mail.version>1.6.2</mail.version>
|
<mail.version>1.6.2</mail.version>
|
||||||
<jsch.version>0.1.55</jsch.version>
|
<jsch.version>0.1.55</jsch.version>
|
||||||
<zxing.version>3.4.0</zxing.version>
|
<zxing.version>3.4.1</zxing.version>
|
||||||
<net.version>3.6</net.version>
|
<net.version>3.7</net.version>
|
||||||
<emoji-java.version>5.1.1</emoji-java.version>
|
<emoji-java.version>5.1.1</emoji-java.version>
|
||||||
<servlet-api.version>4.0.1</servlet-api.version>
|
<servlet-api.version>4.0.1</servlet-api.version>
|
||||||
<spring-boot.version>2.3.4.RELEASE</spring-boot.version>
|
<spring-boot.version>2.3.4.RELEASE</spring-boot.version>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-http</artifactId>
|
<artifactId>hutool-http</artifactId>
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import java.io.OutputStream;
|
|||||||
import java.net.CookieManager;
|
import java.net.CookieManager;
|
||||||
import java.net.HttpCookie;
|
import java.net.HttpCookie;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
import java.net.Proxy;
|
import java.net.Proxy;
|
||||||
import java.net.URLStreamHandler;
|
import java.net.URLStreamHandler;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -841,6 +842,20 @@ public class HttpRequest extends HttpBase<HttpRequest> {
|
|||||||
return this;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 设置代理
|
* 设置代理
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-json</artifactId>
|
<artifactId>hutool-json</artifactId>
|
||||||
|
|||||||
@@ -154,4 +154,11 @@ public class JSONUtilTest {
|
|||||||
Assert.assertEquals("aa", json.get("name"));
|
Assert.assertEquals("aa", json.get("name"));
|
||||||
Assert.assertEquals(1, json.get("gender"));
|
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());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-log</artifactId>
|
<artifactId>hutool-log</artifactId>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-poi</artifactId>
|
<artifactId>hutool-poi</artifactId>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
package cn.hutool.poi.excel;
|
package cn.hutool.poi.excel;
|
||||||
|
|
||||||
import cn.hutool.core.io.IORuntimeException;
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
|
import cn.hutool.core.io.IoUtil;
|
||||||
import org.apache.poi.poifs.filesystem.FileMagic;
|
import org.apache.poi.poifs.filesystem.FileMagic;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@@ -48,11 +49,24 @@ public class ExcelFileUtil {
|
|||||||
* @return 是否为XLSX格式的Excel文件(XSSF)
|
* @return 是否为XLSX格式的Excel文件(XSSF)
|
||||||
*/
|
*/
|
||||||
public static boolean isXlsx(InputStream in) {
|
public static boolean isXlsx(InputStream in) {
|
||||||
if (false == in.markSupported()) {
|
|
||||||
in = new BufferedInputStream(in);
|
|
||||||
}
|
|
||||||
try {
|
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)<br>
|
||||||
|
* 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) {
|
} catch (IOException e) {
|
||||||
throw new IORuntimeException(e);
|
throw new IORuntimeException(e);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package cn.hutool.poi.excel;
|
|||||||
|
|
||||||
import cn.hutool.core.exceptions.DependencyException;
|
import cn.hutool.core.exceptions.DependencyException;
|
||||||
import cn.hutool.core.io.FileUtil;
|
import cn.hutool.core.io.FileUtil;
|
||||||
import cn.hutool.core.io.IoUtil;
|
|
||||||
import cn.hutool.core.util.ObjectUtil;
|
import cn.hutool.core.util.ObjectUtil;
|
||||||
import cn.hutool.core.util.ReUtil;
|
import cn.hutool.core.util.ReUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
@@ -10,9 +9,10 @@ import cn.hutool.poi.PoiChecker;
|
|||||||
import cn.hutool.poi.excel.cell.CellLocation;
|
import cn.hutool.poi.excel.cell.CellLocation;
|
||||||
import cn.hutool.poi.excel.sax.Excel03SaxReader;
|
import cn.hutool.poi.excel.sax.Excel03SaxReader;
|
||||||
import cn.hutool.poi.excel.sax.Excel07SaxReader;
|
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 cn.hutool.poi.excel.sax.handler.RowHandler;
|
||||||
|
|
||||||
import java.io.BufferedInputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
@@ -29,67 +29,92 @@ public class ExcelUtil {
|
|||||||
* 通过Sax方式读取Excel,同时支持03和07格式
|
* 通过Sax方式读取Excel,同时支持03和07格式
|
||||||
*
|
*
|
||||||
* @param path Excel文件路径
|
* @param path Excel文件路径
|
||||||
* @param sheetIndex sheet序号
|
* @param rid sheet rid,-1表示全部Sheet, 0表示第一个Sheet
|
||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
*/
|
*/
|
||||||
public static void readBySax(String path, int sheetIndex, RowHandler rowHandler) {
|
public static void readBySax(String path, int rid, RowHandler rowHandler) {
|
||||||
BufferedInputStream in = null;
|
readBySax(FileUtil.file(path), rid, rowHandler);
|
||||||
try {
|
|
||||||
in = FileUtil.getInputStream(path);
|
|
||||||
readBySax(in, sheetIndex, rowHandler);
|
|
||||||
} finally {
|
|
||||||
IoUtil.close(in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过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格式
|
* 通过Sax方式读取Excel,同时支持03和07格式
|
||||||
*
|
*
|
||||||
* @param file Excel文件
|
* @param file Excel文件
|
||||||
* @param sheetIndex sheet序号
|
* @param rid sheet rid,-1表示全部Sheet, 0表示第一个Sheet
|
||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
*/
|
*/
|
||||||
public static void readBySax(File file, int sheetIndex, RowHandler rowHandler) {
|
public static void readBySax(File file, int rid, RowHandler rowHandler) {
|
||||||
BufferedInputStream in = null;
|
final ExcelSaxReader<?> reader = ExcelSaxUtil.createSaxReader(ExcelFileUtil.isXlsx(file), rowHandler);
|
||||||
try {
|
reader.read(file, rid);
|
||||||
in = FileUtil.getInputStream(file);
|
|
||||||
readBySax(in, sheetIndex, rowHandler);
|
|
||||||
} finally {
|
|
||||||
IoUtil.close(in);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过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格式
|
* 通过Sax方式读取Excel,同时支持03和07格式
|
||||||
*
|
*
|
||||||
* @param in Excel流
|
* @param in Excel流
|
||||||
* @param sheetIndex sheet序号
|
* @param rid sheet rid,-1表示全部Sheet, 0表示第一个Sheet
|
||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
*/
|
*/
|
||||||
public static void readBySax(InputStream in, int sheetIndex, RowHandler rowHandler) {
|
public static void readBySax(InputStream in, int rid, RowHandler rowHandler) {
|
||||||
in = IoUtil.toMarkSupportStream(in);
|
final ExcelSaxReader<?> reader = ExcelSaxUtil.createSaxReader(ExcelFileUtil.isXlsx(in), rowHandler);
|
||||||
if (ExcelFileUtil.isXlsx(in)) {
|
reader.read(in, rid);
|
||||||
read07BySax(in, sheetIndex, rowHandler);
|
|
||||||
} else {
|
|
||||||
read03BySax(in, sheetIndex, rowHandler);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 通过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
|
* Sax方式读取Excel07
|
||||||
*
|
*
|
||||||
* @param in 输入流
|
* @param in 输入流
|
||||||
* @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet
|
* @param rid Sheet rid,-1表示全部Sheet, 0表示第一个Sheet
|
||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @return {@link Excel07SaxReader}
|
* @return {@link Excel07SaxReader}
|
||||||
* @since 3.2.0
|
* @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 {
|
try {
|
||||||
return new Excel07SaxReader(rowHandler).read(in, sheetIndex);
|
return new Excel07SaxReader(rowHandler).read(in, rid);
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG);
|
throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG);
|
||||||
}
|
}
|
||||||
@@ -99,14 +124,16 @@ public class ExcelUtil {
|
|||||||
* Sax方式读取Excel07
|
* Sax方式读取Excel07
|
||||||
*
|
*
|
||||||
* @param file 文件
|
* @param file 文件
|
||||||
* @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet
|
* @param rid Sheet rid,-1表示全部Sheet, 0表示第一个Sheet
|
||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @return {@link Excel07SaxReader}
|
* @return {@link Excel07SaxReader}
|
||||||
* @since 3.2.0
|
* @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 {
|
try {
|
||||||
return new Excel07SaxReader(rowHandler).read(file, sheetIndex);
|
return new Excel07SaxReader(rowHandler).read(file, rid);
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG);
|
throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG);
|
||||||
}
|
}
|
||||||
@@ -116,14 +143,16 @@ public class ExcelUtil {
|
|||||||
* Sax方式读取Excel07
|
* Sax方式读取Excel07
|
||||||
*
|
*
|
||||||
* @param path 路径
|
* @param path 路径
|
||||||
* @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet
|
* @param rid Sheet rid,-1表示全部Sheet, 0表示第一个Sheet
|
||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @return {@link Excel07SaxReader}
|
* @return {@link Excel07SaxReader}
|
||||||
* @since 3.2.0
|
* @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 {
|
try {
|
||||||
return new Excel07SaxReader(rowHandler).read(path, sheetIndex);
|
return new Excel07SaxReader(rowHandler).read(path, rid);
|
||||||
} catch (NoClassDefFoundError e) {
|
} catch (NoClassDefFoundError e) {
|
||||||
throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG);
|
throw new DependencyException(ObjectUtil.defaultIfNull(e.getCause(), e), PoiChecker.NO_POI_ERROR_MSG);
|
||||||
}
|
}
|
||||||
@@ -135,9 +164,11 @@ public class ExcelUtil {
|
|||||||
* @param in 输入流
|
* @param in 输入流
|
||||||
* @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet
|
* @param sheetIndex Sheet索引,-1表示全部Sheet, 0表示第一个Sheet
|
||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @return {@link Excel07SaxReader}
|
* @return {@link Excel03SaxReader}
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
|
* @deprecated 请使用 {@link #readBySax(InputStream, int, RowHandler)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static Excel03SaxReader read03BySax(InputStream in, int sheetIndex, RowHandler rowHandler) {
|
public static Excel03SaxReader read03BySax(InputStream in, int sheetIndex, RowHandler rowHandler) {
|
||||||
try {
|
try {
|
||||||
return new Excel03SaxReader(rowHandler).read(in, sheetIndex);
|
return new Excel03SaxReader(rowHandler).read(in, sheetIndex);
|
||||||
@@ -154,7 +185,9 @@ public class ExcelUtil {
|
|||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @return {@link Excel03SaxReader}
|
* @return {@link Excel03SaxReader}
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
|
* @deprecated 请使用 {@link #readBySax(File, int, RowHandler)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static Excel03SaxReader read03BySax(File file, int sheetIndex, RowHandler rowHandler) {
|
public static Excel03SaxReader read03BySax(File file, int sheetIndex, RowHandler rowHandler) {
|
||||||
try {
|
try {
|
||||||
return new Excel03SaxReader(rowHandler).read(file, sheetIndex);
|
return new Excel03SaxReader(rowHandler).read(file, sheetIndex);
|
||||||
@@ -171,7 +204,9 @@ public class ExcelUtil {
|
|||||||
* @param rowHandler 行处理器
|
* @param rowHandler 行处理器
|
||||||
* @return {@link Excel03SaxReader}
|
* @return {@link Excel03SaxReader}
|
||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
|
* @deprecated 请使用 {@link #readBySax(String, int, RowHandler)}
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public static Excel03SaxReader read03BySax(String path, int sheetIndex, RowHandler rowHandler) {
|
public static Excel03SaxReader read03BySax(String path, int sheetIndex, RowHandler rowHandler) {
|
||||||
try {
|
try {
|
||||||
return new Excel03SaxReader(rowHandler).read(path, sheetIndex);
|
return new Excel03SaxReader(rowHandler).read(path, sheetIndex);
|
||||||
|
|||||||
@@ -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 <T> 子对象类型,用于标记返回值this
|
|
||||||
* @since 3.2.0
|
|
||||||
*/
|
|
||||||
public abstract class AbstractExcelSaxReader<T> implements ExcelSaxReader<T> {
|
|
||||||
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -30,7 +30,7 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author looly
|
* @author looly
|
||||||
*/
|
*/
|
||||||
public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> implements HSSFListener {
|
public class Excel03SaxReader implements HSSFListener, ExcelSaxReader<Excel03SaxReader> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 如果为公式,true表示输出公式计算后的结果值,false表示输出公式本身
|
* 如果为公式,true表示输出公式计算后的结果值,false表示输出公式本身
|
||||||
@@ -83,18 +83,18 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
|
|||||||
|
|
||||||
// ------------------------------------------------------------------------------ Read start
|
// ------------------------------------------------------------------------------ Read start
|
||||||
@Override
|
@Override
|
||||||
public Excel03SaxReader read(File file, int rid) throws POIException {
|
public Excel03SaxReader read(File file, String idOrRid) throws POIException {
|
||||||
try {
|
try {
|
||||||
return read(new POIFSFileSystem(file), rid);
|
return read(new POIFSFileSystem(file), idOrRid);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new POIException(e);
|
throw new POIException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Excel03SaxReader read(InputStream excelStream, int rid) throws POIException {
|
public Excel03SaxReader read(InputStream excelStream, String idOrRid) throws POIException {
|
||||||
try {
|
try {
|
||||||
return read(new POIFSFileSystem(excelStream), rid);
|
return read(new POIFSFileSystem(excelStream), idOrRid);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new POIException(e);
|
throw new POIException(e);
|
||||||
}
|
}
|
||||||
@@ -104,12 +104,12 @@ public class Excel03SaxReader extends AbstractExcelSaxReader<Excel03SaxReader> i
|
|||||||
* 读取
|
* 读取
|
||||||
*
|
*
|
||||||
* @param fs {@link POIFSFileSystem}
|
* @param fs {@link POIFSFileSystem}
|
||||||
* @param rid sheet序号
|
* @param id sheet序号
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException IO异常包装
|
* @throws POIException IO异常包装
|
||||||
*/
|
*/
|
||||||
public Excel03SaxReader read(POIFSFileSystem fs, int rid) throws POIException {
|
public Excel03SaxReader read(POIFSFileSystem fs, String id) throws POIException {
|
||||||
this.rid = rid;
|
this.rid = Integer.parseInt(id);
|
||||||
|
|
||||||
formatListener = new FormatTrackingHSSFListener(new MissingRecordAwareHSSFListener(this));
|
formatListener = new FormatTrackingHSSFListener(new MissingRecordAwareHSSFListener(this));
|
||||||
final HSSFRequest request = new HSSFRequest();
|
final HSSFRequest request = new HSSFRequest();
|
||||||
|
|||||||
@@ -1,10 +1,14 @@
|
|||||||
package cn.hutool.poi.excel.sax;
|
package cn.hutool.poi.excel.sax;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
import cn.hutool.core.io.IoUtil;
|
import cn.hutool.core.io.IoUtil;
|
||||||
import cn.hutool.core.text.StrBuilder;
|
import cn.hutool.core.text.StrBuilder;
|
||||||
|
import cn.hutool.core.util.NumberUtil;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import cn.hutool.poi.excel.sax.handler.RowHandler;
|
import cn.hutool.poi.excel.sax.handler.RowHandler;
|
||||||
import cn.hutool.poi.exceptions.POIException;
|
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.openxml4j.opc.OPCPackage;
|
||||||
import org.apache.poi.ss.usermodel.BuiltinFormats;
|
import org.apache.poi.ss.usermodel.BuiltinFormats;
|
||||||
import org.apache.poi.xssf.eventusermodel.XSSFReader;
|
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.model.StylesTable;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||||
import org.xml.sax.Attributes;
|
import org.xml.sax.Attributes;
|
||||||
import org.xml.sax.ContentHandler;
|
import org.xml.sax.helpers.DefaultHandler;
|
||||||
import org.xml.sax.Locator;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@@ -28,7 +32,7 @@ import java.util.List;
|
|||||||
* @author Looly
|
* @author Looly
|
||||||
* @since 3.1.2
|
* @since 3.1.2
|
||||||
*/
|
*/
|
||||||
public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> implements ContentHandler {
|
public class Excel07SaxReader extends DefaultHandler implements ExcelSaxReader<Excel07SaxReader> {
|
||||||
|
|
||||||
// sheet r:Id前缀
|
// sheet r:Id前缀
|
||||||
private static final String RID_PREFIX = "rId";
|
private static final String RID_PREFIX = "rId";
|
||||||
@@ -92,20 +96,30 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
// ------------------------------------------------------------------------------ Read start
|
// ------------------------------------------------------------------------------ Read start
|
||||||
@Override
|
@Override
|
||||||
public Excel07SaxReader read(File file, int rid) throws POIException {
|
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 {
|
try {
|
||||||
return read(OPCPackage.open(file), rid);
|
return read(OPCPackage.open(file), idOrRid);
|
||||||
} catch (Exception e) {
|
} catch (InvalidFormatException e) {
|
||||||
throw new POIException(e);
|
throw new POIException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Excel07SaxReader read(InputStream in, int rid) throws POIException {
|
public Excel07SaxReader read(InputStream in, int rid) throws POIException {
|
||||||
try {
|
return read(in, RID_PREFIX + rid);
|
||||||
return read(OPCPackage.open(in), rid);
|
}
|
||||||
} catch (RuntimeException e) {
|
|
||||||
throw e;
|
@Override
|
||||||
} catch (Exception e) {
|
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);
|
throw new POIException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -113,53 +127,60 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
/**
|
/**
|
||||||
* 开始读取Excel,Sheet编号从0开始计数
|
* 开始读取Excel,Sheet编号从0开始计数
|
||||||
*
|
*
|
||||||
* @param opcPackage {@link OPCPackage},Excel包
|
* @param opcPackage {@link OPCPackage},Excel包,读取后不关闭
|
||||||
* @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet
|
* @param rid Excel中的sheet rid编号,如果为-1处理所有编号的sheet
|
||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
public Excel07SaxReader read(OPCPackage opcPackage, int rid) throws POIException {
|
public Excel07SaxReader read(OPCPackage opcPackage, int rid) throws POIException {
|
||||||
InputStream sheetInputStream = null;
|
return read(opcPackage, RID_PREFIX + rid);
|
||||||
try {
|
}
|
||||||
final XSSFReader xssfReader = new XSSFReader(opcPackage);
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始读取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 {
|
||||||
|
return read(new XSSFReader(opcPackage), idOrRid);
|
||||||
|
} catch (OpenXML4JException e) {
|
||||||
|
throw new POIException(e);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IORuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始读取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 {
|
try {
|
||||||
stylesTable = xssfReader.getStylesTable();
|
stylesTable = xssfReader.getStylesTable();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
//ignore
|
//ignore
|
||||||
}
|
}
|
||||||
// 获取共享字符串表
|
|
||||||
this.sharedStringsTable = xssfReader.getSharedStringsTable();
|
|
||||||
|
|
||||||
if (rid > -1) {
|
// 获取共享字符串表
|
||||||
this.sheetIndex = rid;
|
try {
|
||||||
// 根据 rId# 或 rSheet# 查找sheet
|
this.sharedStringsTable = xssfReader.getSharedStringsTable();
|
||||||
sheetInputStream = xssfReader.getSheet(RID_PREFIX + (rid + 1));
|
} catch (IOException e) {
|
||||||
ExcelSaxUtil.readFrom(sheetInputStream, this);
|
throw new IORuntimeException(e);
|
||||||
rowHandler.doAfterAllAnalysed();
|
} catch (InvalidFormatException e) {
|
||||||
} else {
|
|
||||||
this.sheetIndex = -1;
|
|
||||||
// 遍历所有sheet
|
|
||||||
final Iterator<InputStream> 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);
|
throw new POIException(e);
|
||||||
} finally {
|
|
||||||
IoUtil.close(sheetInputStream);
|
|
||||||
IoUtil.close(opcPackage);
|
|
||||||
}
|
}
|
||||||
return this;
|
|
||||||
|
return readSheets(xssfReader, idOrRid);
|
||||||
}
|
}
|
||||||
// ------------------------------------------------------------------------------ Read end
|
// ------------------------------------------------------------------------------ Read end
|
||||||
|
|
||||||
@@ -196,53 +217,57 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
lastContent.append(ch, start, length);
|
lastContent.append(ch, start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------- Pass method start
|
// --------------------------------------------------------------------------------------- Private method start
|
||||||
@Override
|
|
||||||
public void setDocumentLocator(Locator locator) {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ?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
|
private Excel07SaxReader readSheets(XSSFReader xssfReader, String idOrRid) throws POIException {
|
||||||
public void startDocument() {
|
// 将sheetId转换为rid
|
||||||
// pass
|
if (NumberUtil.isInteger(idOrRid)) {
|
||||||
|
final SheetRidReader ridReader = new SheetRidReader();
|
||||||
|
final String rid = ridReader.read(xssfReader).getRidBySheetId(idOrRid);
|
||||||
|
if (StrUtil.isNotEmpty(rid)) {
|
||||||
|
idOrRid = rid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void endDocument() {
|
|
||||||
// pass
|
|
||||||
}
|
}
|
||||||
|
this.sheetIndex = Integer.parseInt(StrUtil.removePrefixIgnoreCase(idOrRid, RID_PREFIX));
|
||||||
@Override
|
InputStream sheetInputStream = null;
|
||||||
public void startPrefixMapping(String prefix, String uri) {
|
try {
|
||||||
// pass
|
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<InputStream> sheetInputStreams = xssfReader.getSheetsData();
|
||||||
|
while (sheetInputStreams.hasNext()) {
|
||||||
|
// 重新读取一个sheet时行归零
|
||||||
|
index = 0;
|
||||||
|
this.sheetIndex++;
|
||||||
|
sheetInputStream = sheetInputStreams.next();
|
||||||
|
ExcelSaxUtil.readFrom(sheetInputStream, this);
|
||||||
|
rowHandler.doAfterAllAnalysed();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void endPrefixMapping(String prefix) {
|
|
||||||
// pass
|
|
||||||
}
|
}
|
||||||
|
} catch (RuntimeException e) {
|
||||||
@Override
|
throw e;
|
||||||
public void ignorableWhitespace(char[] ch, int start, int length) {
|
} catch (Exception e) {
|
||||||
// pass
|
throw new POIException(e);
|
||||||
|
} finally {
|
||||||
|
IoUtil.close(sheetInputStream);
|
||||||
}
|
}
|
||||||
|
return this;
|
||||||
@Override
|
|
||||||
public void processingInstruction(String target, String data) {
|
|
||||||
// pass
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void skippedEntity(String name) {
|
|
||||||
// pass
|
|
||||||
}
|
|
||||||
// --------------------------------------------------------------------------------------- Pass method end
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------- Private method start
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 行开始
|
* 行开始
|
||||||
*
|
*
|
||||||
@@ -317,6 +342,7 @@ public class Excel07SaxReader extends AbstractExcelSaxReader<Excel07SaxReader> i
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* 在一行中的指定列增加值
|
* 在一行中的指定列增加值
|
||||||
|
*
|
||||||
* @param index 位置
|
* @param index 位置
|
||||||
* @param value 值
|
* @param value 值
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package cn.hutool.poi.excel.sax;
|
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.File;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
import cn.hutool.poi.exceptions.POIException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sax方式读取Excel接口,提供一些共用方法
|
* Sax方式读取Excel接口,提供一些共用方法
|
||||||
* @author looly
|
* @author looly
|
||||||
@@ -13,6 +14,27 @@ import cn.hutool.poi.exceptions.POIException;
|
|||||||
* @since 3.2.0
|
* @since 3.2.0
|
||||||
*/
|
*/
|
||||||
public interface ExcelSaxReader<T> {
|
public interface ExcelSaxReader<T> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 开始读取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
|
* 开始读取Excel,读取所有sheet
|
||||||
*
|
*
|
||||||
@@ -20,7 +42,9 @@ public interface ExcelSaxReader<T> {
|
|||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
T read(String path) throws POIException;
|
default T read(String path) throws POIException {
|
||||||
|
return read(FileUtil.file(path));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel,读取所有sheet
|
* 开始读取Excel,读取所有sheet
|
||||||
@@ -29,7 +53,9 @@ public interface ExcelSaxReader<T> {
|
|||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
T read(File file) throws POIException;
|
default T read(File file) throws POIException {
|
||||||
|
return read(file, -1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel,读取所有sheet,读取结束后并不关闭流
|
* 开始读取Excel,读取所有sheet,读取结束后并不关闭流
|
||||||
@@ -38,7 +64,9 @@ public interface ExcelSaxReader<T> {
|
|||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @throws POIException POI异常
|
||||||
*/
|
*/
|
||||||
T read(InputStream in) throws POIException;
|
default T read(InputStream in) throws POIException {
|
||||||
|
return read(in, -1);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 开始读取Excel
|
* 开始读取Excel
|
||||||
@@ -48,7 +76,21 @@ public interface ExcelSaxReader<T> {
|
|||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @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
|
* 开始读取Excel
|
||||||
@@ -58,7 +100,9 @@ public interface ExcelSaxReader<T> {
|
|||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @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,读取结束后并不关闭流
|
* 开始读取Excel,读取结束后并不关闭流
|
||||||
@@ -68,5 +112,7 @@ public interface ExcelSaxReader<T> {
|
|||||||
* @return this
|
* @return this
|
||||||
* @throws POIException POI异常
|
* @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));
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import cn.hutool.core.date.DateUtil;
|
|||||||
import cn.hutool.core.exceptions.DependencyException;
|
import cn.hutool.core.exceptions.DependencyException;
|
||||||
import cn.hutool.core.io.IORuntimeException;
|
import cn.hutool.core.io.IORuntimeException;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.poi.excel.sax.handler.RowHandler;
|
||||||
import cn.hutool.poi.exceptions.POIException;
|
import cn.hutool.poi.exceptions.POIException;
|
||||||
import org.apache.poi.ooxml.util.SAXHelper;
|
import org.apache.poi.ooxml.util.SAXHelper;
|
||||||
import org.apache.poi.ss.usermodel.DataFormatter;
|
import org.apache.poi.ss.usermodel.DataFormatter;
|
||||||
@@ -150,6 +151,7 @@ public class ExcelSaxUtil {
|
|||||||
public static void readFrom(InputStream xmlDocStream, ContentHandler handler) throws DependencyException, POIException, IORuntimeException {
|
public static void readFrom(InputStream xmlDocStream, ContentHandler handler) throws DependencyException, POIException, IORuntimeException {
|
||||||
XMLReader xmlReader;
|
XMLReader xmlReader;
|
||||||
try {
|
try {
|
||||||
|
// xmlReader = XMLReaderFactory.createXMLReader();
|
||||||
//noinspection deprecation
|
//noinspection deprecation
|
||||||
xmlReader = SAXHelper.newXMLReader();
|
xmlReader = SAXHelper.newXMLReader();
|
||||||
} catch (SAXException | ParserConfigurationException e) {
|
} catch (SAXException | ParserConfigurationException e) {
|
||||||
@@ -191,6 +193,20 @@ public class ExcelSaxUtil {
|
|||||||
return DateUtil.date(org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value, false));
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取数字类型值
|
* 获取数字类型值
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -0,0 +1,111 @@
|
|||||||
|
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的对应关系,类似于:
|
||||||
|
* <pre>
|
||||||
|
* <sheet name="Sheet6" sheetId="4" r:id="6"/>
|
||||||
|
* </pre>
|
||||||
|
* <p>
|
||||||
|
* 读取结果为:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
* {"4": "6"}
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* @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<String, String> ID_RID_MAP = new HashMap<>();
|
||||||
|
private final Map<String, String> NAME_RID_MAP = new HashMap<>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 读取Wordkbook的XML中sheet标签中sheetId和rid的对应关系
|
||||||
|
*
|
||||||
|
* @param xssfReader XSSF读取器
|
||||||
|
* @return this
|
||||||
|
*/
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,7 +25,7 @@ public class ExcelSaxReadTest {
|
|||||||
@Test
|
@Test
|
||||||
public void excel07Test() {
|
public void excel07Test() {
|
||||||
// 工具化快速读取
|
// 工具化快速读取
|
||||||
ExcelUtil.read07BySax("aaa.xlsx", 0, createRowHandler());
|
ExcelUtil.readBySax("aaa.xlsx", 0, createRowHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -33,7 +33,7 @@ public class ExcelSaxReadTest {
|
|||||||
Excel03SaxReader reader = new Excel03SaxReader(createRowHandler());
|
Excel03SaxReader reader = new Excel03SaxReader(createRowHandler());
|
||||||
reader.read("aaa.xls", 1);
|
reader.read("aaa.xls", 1);
|
||||||
// Console.log("Sheet index: [{}], Sheet name: [{}]", reader.getSheetIndex(), reader.getSheetName());
|
// Console.log("Sheet index: [{}], Sheet name: [{}]", reader.getSheetIndex(), reader.getSheetName());
|
||||||
ExcelUtil.read03BySax("aaa.xls", 1, createRowHandler());
|
ExcelUtil.readBySax("aaa.xls", 1, createRowHandler());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-script</artifactId>
|
<artifactId>hutool-script</artifactId>
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
<properties>
|
<properties>
|
||||||
<jython.version>2.7.2</jython.version>
|
<jython.version>2.7.2</jython.version>
|
||||||
<luaj.version>3.0.1</luaj.version>
|
<luaj.version>3.0.1</luaj.version>
|
||||||
<groovy.version>3.0.2</groovy.version>
|
<groovy.version>3.0.6</groovy.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-setting</artifactId>
|
<artifactId>hutool-setting</artifactId>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-socket</artifactId>
|
<artifactId>hutool-socket</artifactId>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<parent>
|
<parent>
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>hutool-system</artifactId>
|
<artifactId>hutool-system</artifactId>
|
||||||
|
|||||||
2
pom.xml
2
pom.xml
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<groupId>cn.hutool</groupId>
|
<groupId>cn.hutool</groupId>
|
||||||
<artifactId>hutool-parent</artifactId>
|
<artifactId>hutool-parent</artifactId>
|
||||||
<version>5.4.4-SNAPSHOT</version>
|
<version>5.4.5-SNAPSHOT</version>
|
||||||
<name>hutool</name>
|
<name>hutool</name>
|
||||||
<description>Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。</description>
|
<description>Hutool是一个小而全的Java工具类库,通过静态方法封装,降低相关API的学习成本,提高工作效率,使Java拥有函数式语言般的优雅,让Java语言也可以“甜甜的”。</description>
|
||||||
<url>https://github.com/looly/hutool</url>
|
<url>https://github.com/looly/hutool</url>
|
||||||
|
|||||||
Reference in New Issue
Block a user