Merge remote-tracking branch 'upstream/v5-dev' into v5-dev

This commit is contained in:
lzpeng723 2020-12-18 18:27:49 +08:00
commit be5ab72a36
50 changed files with 519 additions and 181 deletions

View File

@ -3,6 +3,24 @@
-------------------------------------------------------------------------------------------------------------
# 5.5.5 (2020-12-17)
### 新特性
* 【core 】 URLUtil.normalize新增重载pr#233@Gitee
* 【core 】 PathUtil增加isSub和toAbsNormal方法
### Bug修复
* 【core 】 FileUtil.isSub相对路径判断问题pr#1315@Github
-------------------------------------------------------------------------------------------------------------
# 5.5.4 (2020-12-16)
### 新特性
### Bug修复
* 【core 】 修复IoUtil.readBytes的问题
-------------------------------------------------------------------------------------------------------------
# 5.5.3 (2020-12-11)
### 新特性
@ -21,6 +39,8 @@
* 【core 】 增加NioUtil
* 【core 】 增加GanymedUtil
* 【poi 】 增加OFD支持OfdWriter
* 【poi 】 修复NumberUtil属性拼写错误pr#1311@Github
* 【core 】 MapUtil增加getQuietly方法issue#I29IWO@Gitee
### Bug修复
* 【cache 】 修复Cache中get重复misCount计数问题issue#1281@Github
@ -34,6 +54,7 @@
* 【core 】 修复FileUtil.loopFiles使用FileFilter无效问题issue#I28V48@Gitee
* 【extra 】 修复JschUtil.execByShell返回空的问题issue#1067@Github
* 【poi 】 修复特殊的excel使用sax读取时未读到值的问题issue#1303@Github
* 【http 】 修复HttpUtil类条件判断错误pr#232@Gitee
-------------------------------------------------------------------------------------------------------------

View File

@ -125,19 +125,19 @@ Each module can be introduced individually, or all modules can be introduced by
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.3</version>
<version>5.5.5</version>
</dependency>
```
### Gradle
```
compile 'cn.hutool:hutool-all:5.5.3'
compile 'cn.hutool:hutool-all:5.5.5'
```
## Download
- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.3/)
- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.3/)
- [Maven1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.5/)
- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.5/)
> note:
> Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available.

View File

@ -123,21 +123,21 @@ Hutool的存在就是为了减少代码搜索成本避免网络上参差不
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.5.3</version>
<version>5.5.5</version>
</dependency>
```
### Gradle
```
compile 'cn.hutool:hutool-all:5.5.3'
compile 'cn.hutool:hutool-all:5.5.5'
```
### 非Maven项目
点击以下任一链接,下载`hutool-all-X.X.X.jar`即可:
- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.3/)
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.3/)
- [Maven中央库1](https://repo1.maven.org/maven2/cn/hutool/hutool-all/5.5.5/)
- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.5/)
> 注意
> Hutool 5.x支持JDK8+对Android平台没有测试不能保证所有工具类或工具方法可用。

View File

@ -1 +1 @@
5.5.3
5.5.5

View File

@ -1 +1 @@
var version = '5.5.3'
var version = '5.5.5'

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-all</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-aop</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-bloomFilter</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-bom</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-cache</artifactId>

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-captcha</artifactId>

View File

@ -17,7 +17,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-core</artifactId>

View File

@ -14,17 +14,17 @@ import java.nio.charset.Charset;
* Base64工具类提供Base64的编码和解码方案<br>
* base64编码是用642的6次方个ASCII字符来表示2562的8次方个ASCII字符<br>
* 也就是三位二进制数组经过编码后变为四位的ASCII字符显示长度比原来增加1/3
*
* @author Looly
*
* @author Looly
*/
public class Base64 {
// -------------------------------------------------------------------- encode
/**
* 编码为Base64非URL安全的
*
* @param arr 被编码的数组
*
* @param arr 被编码的数组
* @param lineSep 在76个char之后是CRLF还是EOF
* @return 编码后的bytes
*/
@ -34,8 +34,8 @@ public class Base64 {
/**
* 编码为Base64URL安全的
*
* @param arr 被编码的数组
*
* @param arr 被编码的数组
* @param lineSep 在76个char之后是CRLF还是EOF
* @return 编码后的bytes
* @since 3.0.6
@ -46,7 +46,7 @@ public class Base64 {
/**
* base64编码
*
*
* @param source 被编码的base64字符串
* @return 被加密后的字符串
*/
@ -56,7 +56,7 @@ public class Base64 {
/**
* base64编码URL安全
*
*
* @param source 被编码的base64字符串
* @return 被加密后的字符串
* @since 3.0.6
@ -67,8 +67,8 @@ public class Base64 {
/**
* base64编码
*
* @param source 被编码的base64字符串
*
* @param source 被编码的base64字符串
* @param charset 字符集
* @return 被加密后的字符串
*/
@ -79,7 +79,8 @@ public class Base64 {
/**
* base64编码不进行padding(末尾不会填充'=')
*
* @param source 被编码的base64字符串
* @param source 被编码的base64字符串
* @param charset 编码
* @return 被加密后的字符串
* @since 5.5.2
*/
@ -89,8 +90,8 @@ public class Base64 {
/**
* base64编码,URL安全
*
* @param source 被编码的base64字符串
*
* @param source 被编码的base64字符串
* @param charset 字符集
* @return 被加密后的字符串
* @since 3.0.6
@ -101,8 +102,8 @@ public class Base64 {
/**
* base64编码
*
* @param source 被编码的base64字符串
*
* @param source 被编码的base64字符串
* @param charset 字符集
* @return 被加密后的字符串
*/
@ -112,8 +113,8 @@ public class Base64 {
/**
* base64编码URL安全的
*
* @param source 被编码的base64字符串
*
* @param source 被编码的base64字符串
* @param charset 字符集
* @return 被加密后的字符串
* @since 3.0.6
@ -124,7 +125,7 @@ public class Base64 {
/**
* base64编码
*
*
* @param source 被编码的base64字符串
* @return 被加密后的字符串
*/
@ -145,7 +146,7 @@ public class Base64 {
/**
* base64编码,URL安全的
*
*
* @param source 被编码的base64字符串
* @return 被加密后的字符串
* @since 3.0.6
@ -156,7 +157,7 @@ public class Base64 {
/**
* base64编码
*
*
* @param in 被编码base64的流一般为图片流或者文件流
* @return 被加密后的字符串
* @since 4.0.9
@ -167,7 +168,7 @@ public class Base64 {
/**
* base64编码,URL安全的
*
*
* @param in 被编码base64的流一般为图片流或者文件流
* @return 被加密后的字符串
* @since 4.0.9
@ -178,7 +179,7 @@ public class Base64 {
/**
* base64编码
*
*
* @param file 被编码base64的文件
* @return 被加密后的字符串
* @since 4.0.9
@ -189,7 +190,7 @@ public class Base64 {
/**
* base64编码,URL安全的
*
*
* @param file 被编码base64的文件
* @return 被加密后的字符串
* @since 4.0.9
@ -200,11 +201,11 @@ public class Base64 {
/**
* 编码为Base64<br>
* 如果isMultiLine为<code>true</code>则每76个字符一个换行符否则在一行显示
*
* @param arr 被编码的数组
* 如果isMultiLine为{@code true}则每76个字符一个换行符否则在一行显示
*
* @param arr 被编码的数组
* @param isMultiLine 在76个char之后是CRLF还是EOF
* @param isUrlSafe 是否使用URL安全字符一般为<code>false</code>
* @param isUrlSafe 是否使用URL安全字符一般为{@code false}
* @return 编码后的bytes
*/
public static byte[] encode(byte[] arr, boolean isMultiLine, boolean isUrlSafe) {
@ -212,9 +213,10 @@ public class Base64 {
}
// -------------------------------------------------------------------- decode
/**
* base64解码
*
*
* @param source 被解码的base64字符串
* @return 被加密后的字符串
* @since 4.3.2
@ -225,7 +227,7 @@ public class Base64 {
/**
* base64解码
*
*
* @param source 被解码的base64字符串
* @return 被加密后的字符串
*/
@ -235,8 +237,8 @@ public class Base64 {
/**
* base64解码
*
* @param source 被解码的base64字符串
*
* @param source 被解码的base64字符串
* @param charset 字符集
* @return 被加密后的字符串
*/
@ -246,8 +248,8 @@ public class Base64 {
/**
* base64解码
*
* @param source 被解码的base64字符串
*
* @param source 被解码的base64字符串
* @param charset 字符集
* @return 被加密后的字符串
*/
@ -257,8 +259,8 @@ public class Base64 {
/**
* base64解码
*
* @param base64 被解码的base64字符串
*
* @param base64 被解码的base64字符串
* @param destFile 目标文件
* @return 目标文件
* @since 4.0.9
@ -269,9 +271,9 @@ public class Base64 {
/**
* base64解码
*
* @param base64 被解码的base64字符串
* @param out 写出到的流
*
* @param base64 被解码的base64字符串
* @param out 写出到的流
* @param isCloseOut 是否关闭输出流
* @since 4.0.9
*/
@ -281,7 +283,7 @@ public class Base64 {
/**
* base64解码
*
*
* @param base64 被解码的base64字符串
* @return 被加密后的字符串
*/
@ -291,11 +293,11 @@ public class Base64 {
/**
* base64解码
*
* @param source 被解码的base64字符串
*
* @param source 被解码的base64字符串
* @param charset 字符集
* @return 被加密后的字符串
*@deprecated 编码参数无意义作废
* @deprecated 编码参数无意义作废
*/
@Deprecated
public static byte[] decode(CharSequence source, String charset) {
@ -304,11 +306,11 @@ public class Base64 {
/**
* base64解码
*
* @param source 被解码的base64字符串
*
* @param source 被解码的base64字符串
* @param charset 字符集
* @return 被加密后的字符串
*@deprecated 编码参数无意义作废
* @deprecated 编码参数无意义作废
*/
@Deprecated
public static byte[] decode(CharSequence source, Charset charset) {
@ -317,7 +319,7 @@ public class Base64 {
/**
* 解码Base64
*
*
* @param in 输入
* @return 解码后的bytes
*/

View File

@ -1,10 +1,10 @@
package cn.hutool.core.codec;
import java.nio.charset.Charset;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import java.nio.charset.Charset;
/**
* Base64编码
*
@ -128,11 +128,11 @@ public class Base64Encoder {
/**
* 编码为Base64<br>
* 如果isMultiLine为<code>true</code>则每76个字符一个换行符否则在一行显示
* 如果isMultiLine为{@code true}则每76个字符一个换行符否则在一行显示
*
* @param arr 被编码的数组
* @param isMultiLine 在76个char之后是CRLF还是EOF
* @param isUrlSafe 是否使用URL安全字符一般为<code>false</code>
* @param isUrlSafe 是否使用URL安全字符一般为{@code false}
* @return 编码后的bytes
*/
public static byte[] encode(byte[] arr, boolean isMultiLine, boolean isUrlSafe) {

View File

@ -49,7 +49,7 @@ public class Convert {
/**
* 转换为字符串<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为{@code null}或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -85,7 +85,7 @@ public class Convert {
/**
* 转换为字符<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为{@code null}或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -108,7 +108,7 @@ public class Convert {
/**
* 转换为byte<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<br>
* 如果给定的值为{@code null}或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -121,7 +121,7 @@ public class Convert {
/**
* 转换为byte<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为{@code null}或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -155,7 +155,7 @@ public class Convert {
/**
* 转换为Short<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<br>
* 如果给定的值为{@code null}或者转换失败返回默认值<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -168,7 +168,7 @@ public class Convert {
/**
* 转换为Short<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为{@code null}或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -204,7 +204,7 @@ public class Convert {
/**
* 转换为Number<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为空或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -240,7 +240,7 @@ public class Convert {
/**
* 转换为int<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为{@code null}或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -275,7 +275,7 @@ public class Convert {
/**
* 转换为long<br>
* 如果给定的值为<code>null</code>或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为{@code null}或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -310,7 +310,7 @@ public class Convert {
/**
* 转换为double<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为空或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -345,7 +345,7 @@ public class Convert {
/**
* 转换为Float<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为空或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -380,7 +380,7 @@ public class Convert {
/**
* 转换为boolean<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为空或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -415,7 +415,7 @@ public class Convert {
/**
* 转换为BigInteger<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为空或者转换失败返回默认值{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -480,7 +480,7 @@ public class Convert {
/**
* 转换为LocalDateTime<br>
* 如果给定的值为空或者转换失败返回<code>null</code><br>
* 如果给定的值为空或者转换失败返回{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -506,7 +506,7 @@ public class Convert {
/**
* 转换为Date<br>
* 如果给定的值为空或者转换失败返回<code>null</code><br>
* 如果给定的值为空或者转换失败返回{@code null}<br>
* 转换失败不会报错
*
* @param value 被转换的值
@ -534,7 +534,7 @@ public class Convert {
/**
* 转换为Enum对象<br>
* 如果给定的值为空或者转换失败返回默认值<code>null</code><br>
* 如果给定的值为空或者转换失败返回默认值{@code null}<br>
*
* @param <E> 枚举类型
* @param clazz Enum的Class

View File

@ -3194,7 +3194,7 @@ public class FileUtil extends PathUtil {
public static boolean isSub(File parent, File sub) {
Assert.notNull(parent);
Assert.notNull(sub);
return sub.toPath().startsWith(parent.toPath());
return isSub(parent.toPath(), sub.toPath());
}
/**

View File

@ -43,7 +43,7 @@ import java.util.zip.Checksum;
*
* @author xiaoleilu
*/
public class IoUtil extends NioUtil{
public class IoUtil extends NioUtil {
// -------------------------------------------------------------------------------------- Copy start
@ -330,7 +330,7 @@ public class IoUtil extends NioUtil{
}
/**
* 从流中读取内容
* 从流中读取内容读取完成后关闭流
*
* @param in 输入流
* @param charsetName 字符集
@ -338,7 +338,7 @@ public class IoUtil extends NioUtil{
* @throws IORuntimeException IO异常
*/
public static String read(InputStream in, String charsetName) throws IORuntimeException {
FastByteArrayOutputStream out = read(in);
final FastByteArrayOutputStream out = read(in);
return StrUtil.isBlank(charsetName) ? out.toString() : out.toString(charsetName);
}
@ -362,8 +362,27 @@ public class IoUtil extends NioUtil{
* @throws IORuntimeException IO异常
*/
public static FastByteArrayOutputStream read(InputStream in) throws IORuntimeException {
return read(in, true);
}
/**
* 从流中读取内容读到输出流中读取完毕后并不关闭流
*
* @param in 输入流
* @param isClose 读取完毕后是否关闭流
* @return 输出流
* @throws IORuntimeException IO异常
* @since 5.5.3
*/
public static FastByteArrayOutputStream read(InputStream in, boolean isClose) throws IORuntimeException {
final FastByteArrayOutputStream out = new FastByteArrayOutputStream();
copy(in, out);
try {
copy(in, out);
} finally {
if (isClose) {
close(in);
}
}
return out;
}
@ -417,26 +436,31 @@ public class IoUtil extends NioUtil{
/**
* 从流中读取bytes
*
* @param in {@link InputStream}
* @param isCloseStream 是否关闭输入流
* @param in {@link InputStream}
* @param isCLose 是否关闭输入流
* @return bytes
* @throws IORuntimeException IO异常
* @since 5.0.4
*/
public static byte[] readBytes(InputStream in, boolean isCloseStream) throws IORuntimeException {
final InputStream availableStream = toAvailableStream(in);
try{
final int available = availableStream.available();
if(available > 0){
byte[] result = new byte[available];
//noinspection ResultOfMethodCallIgnored
availableStream.read(result);
return result;
public static byte[] readBytes(InputStream in, boolean isCLose) throws IORuntimeException {
if (in instanceof FileInputStream) {
// 文件流的长度是可预见的此时直接读取效率更高
final byte[] result;
try {
final int available = in.available();
result = new byte[available];
final int readLength = in.read(result);
if (readLength != available) {
throw new IOException(StrUtil.format("File length is [{}] but read [{}]!", available, readLength));
}
} catch (IOException e) {
throw new IORuntimeException(e);
}
} catch (IOException e){
throw new IORuntimeException(e);
return result;
}
return new byte[0];
// 未知bytes总量的流
return read(in, isCLose).toByteArray();
}
/**
@ -804,6 +828,7 @@ public class IoUtil extends NioUtil{
* 将指定{@link InputStream} 转换为{@link InputStream#available()}方法可用的流<br>
* 在Socket通信流中服务端未返回数据情况下{@link InputStream#available()}方法始终为{@code 0}<br>
* 因此在读取前需要调用{@link InputStream#read()}读取一个字节未返回会阻塞一旦读取到了{@link InputStream#available()}方法就正常了<br>
* 需要注意的是在网络流中是按照块来传输的所以 {@link InputStream#available()} 读取到的并非最终长度而是此次块的长度<br>
* 此方法返回对象的规则为
*
* <ul>
@ -816,7 +841,7 @@ public class IoUtil extends NioUtil{
* @since 5.5.3
*/
public static InputStream toAvailableStream(InputStream in) {
if(in instanceof FileInputStream){
if (in instanceof FileInputStream) {
// FileInputStream本身支持available方法
return in;
}

View File

@ -94,8 +94,8 @@ public class PathUtil {
/**
* 遍历指定path下的文件并做处理
*
* @param start 起始路径必须为目录
* @param visitor {@link FileVisitor} 接口用于自定义在访问文件时访问目录前后等节点做的操作
* @param start 起始路径必须为目录
* @param visitor {@link FileVisitor} 接口用于自定义在访问文件时访问目录前后等节点做的操作
* @see Files#walkFileTree(Path, java.util.Set, int, FileVisitor)
* @since 5.5.2
*/
@ -169,7 +169,7 @@ public class PathUtil {
* 通过JDK7+ {@link Files#copy(Path, Path, CopyOption...)} 方法拷贝文件
*
* @param src 源文件路径如果为目录只在目标中创建新目录
* @param target 目标文件或目录如果为目录使用与源文件相同的文件名
* @param target 目标文件或目录如果为目录使用与源文件相同的文件名
* @param options {@link StandardCopyOption}
* @return Path
* @throws IORuntimeException IO异常
@ -191,14 +191,14 @@ public class PathUtil {
* 拷贝文件或目录
*
* @param src 源文件路径如果为目录只在目标中创建新目录
* @param target 目标文件或目录如果为目录使用与源文件相同的文件名
* @param target 目标文件或目录如果为目录使用与源文件相同的文件名
* @param options {@link StandardCopyOption}
* @return Path
* @throws IORuntimeException IO异常
* @since 5.5.1
*/
public static Path copy(Path src, Path target, CopyOption... options) throws IORuntimeException {
if(isFile(src, false)){
if (isFile(src, false)) {
return copyFile(src, target, options);
}
return copyContent(src, target.resolve(src.getFileName()), options);
@ -208,7 +208,7 @@ public class PathUtil {
* 拷贝目录下的所有文件或目录到目标目录中
*
* @param src 源文件路径如果为目录只在目标中创建新目录
* @param target 目标文件或目录如果为目录使用与源文件相同的文件名
* @param target 目标文件或目录如果为目录使用与源文件相同的文件名
* @param options {@link StandardCopyOption}
* @return Path
* @throws IORuntimeException IO异常
@ -227,7 +227,7 @@ public class PathUtil {
* 判断是否为目录如果file为null则返回false<br>
* 此方法不会追踪到软链对应的真实地址即软链被当作文件
*
* @param path {@link Path}
* @param path {@link Path}
* @return 如果为目录true
* @since 5.5.1
*/
@ -383,6 +383,21 @@ public class PathUtil {
return IoUtil.getReader(getInputStream(path), charset);
}
/**
* 读取文件的所有内容为byte数组
*
* @param path 文件
* @return byte数组
* @since 5.5.4
*/
public static byte[] readBytes(Path path){
try {
return Files.readAllBytes(path);
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
/**
* 获得输出流
*
@ -487,4 +502,56 @@ public class PathUtil {
public static boolean isSymlink(Path path) {
return Files.isSymbolicLink(path);
}
/**
* 判断文件或目录是否存在
*
* @param path 文件
* @param isFollowLinks 是否跟踪软链快捷方式
* @return 是否存在
* @since 5.5.3
*/
public static boolean exists(Path path, boolean isFollowLinks) {
final LinkOption[] options = isFollowLinks ? new LinkOption[0] : new LinkOption[]{LinkOption.NOFOLLOW_LINKS};
return Files.exists(path, options);
}
/**
* 判断给定的目录是否为给定文件或文件夹的子目录
*
* @param parent 父目录
* @param sub 子目录
* @return 子目录是否为父目录的子目录
* @since 5.5.5
*/
public static boolean isSub(Path parent, Path sub) {
return toAbsNormal(sub).startsWith(toAbsNormal(parent));
}
/**
* 将Path路径转换为标准的绝对路径
*
* @param path 文件或目录Path
* @return 转换后的Path
* @since 5.5.5
*/
public static Path toAbsNormal(Path path){
Assert.notNull(path);
return path.toAbsolutePath().normalize();
}
/**
* 获得文件的MimeType
*
* @param file 文件
* @return MimeType
* @since 5.5.5
*/
public static String getMimeType(Path file) {
try {
return Files.probeContentType(file);
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
}

View File

@ -1160,6 +1160,21 @@ public class MapUtil {
return null == map ? null : Convert.convert(type, map.get(key), defaultValue);
}
/**
* 获取Map指定key的值并转换为指定类型此方法在转换失败后不抛异常返回null
*
* @param <T> 目标值类型
* @param map Map
* @param key
* @param type 值类型
* @param defaultValue 默认值
* @return
* @since 5.5.3
*/
public static <T> T getQuietly(Map<?, ?> map, Object key, Class<T> type, T defaultValue) {
return null == map ? null : Convert.convertQuietly(type, map.get(key), defaultValue);
}
/**
* 获取Map指定key的值并转换为指定类型
*
@ -1189,6 +1204,21 @@ public class MapUtil {
return null == map ? null : Convert.convert(type, map.get(key), defaultValue);
}
/**
* 获取Map指定key的值并转换为指定类型转换失败后返回null不抛异常
*
* @param <T> 目标值类型
* @param map Map
* @param key
* @param type 值类型
* @param defaultValue 默认值
* @return
* @since 5.5.3
*/
public static <T> T getQuietly(Map<?, ?> map, Object key, TypeReference<T> type, T defaultValue) {
return null == map ? null : Convert.convertQuietly(type, map.get(key), defaultValue);
}
/**
* 重命名键<br>
* 实现方式为一处然后重新put当旧的key不存在直接返回<br>

View File

@ -0,0 +1,41 @@
package cn.hutool.core.net;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
/**
* 账号密码形式的{@link Authenticator} 实现
*
* @author looly
* @since 5.5.3
*/
public class PassAuth extends Authenticator {
/**
* 创建账号密码形式的{@link Authenticator} 实现
*
* @param user 用户名
* @param pass 密码
* @return PassAuth
*/
public static PassAuth of(String user, char[] pass) {
return new PassAuth(user, pass);
}
private final PasswordAuthentication auth;
/**
* 构造
*
* @param user 用户名
* @param pass 密码
*/
public PassAuth(String user, char[] pass) {
auth = new PasswordAuthentication(user, pass);
}
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return auth;
}
}

View File

@ -4146,7 +4146,7 @@ public class CharSequenceUtil {
if (null == str) {
return null;
}
if (str.length() <= maxLength) {
if (maxLength <= 0 || str.length() <= maxLength) {
return str.toString();
}
int w = maxLength / 2;

View File

@ -41,7 +41,7 @@ public class NumberUtil {
/**
* 默认除法运算精度
*/
private static final int DEFAUT_DIV_SCALE = 10;
private static final int DEFAULT_DIV_SCALE = 10;
/**
* 0-20对应的阶乘超过20的阶乘会超过Long.MAX_VALUE
@ -484,7 +484,7 @@ public class NumberUtil {
* @return 两个参数的商
*/
public static double div(float v1, float v2) {
return div(v1, v2, DEFAUT_DIV_SCALE);
return div(v1, v2, DEFAULT_DIV_SCALE);
}
/**
@ -495,7 +495,7 @@ public class NumberUtil {
* @return 两个参数的商
*/
public static double div(float v1, double v2) {
return div(v1, v2, DEFAUT_DIV_SCALE);
return div(v1, v2, DEFAULT_DIV_SCALE);
}
/**
@ -506,7 +506,7 @@ public class NumberUtil {
* @return 两个参数的商
*/
public static double div(double v1, float v2) {
return div(v1, v2, DEFAUT_DIV_SCALE);
return div(v1, v2, DEFAULT_DIV_SCALE);
}
/**
@ -517,7 +517,7 @@ public class NumberUtil {
* @return 两个参数的商
*/
public static double div(double v1, double v2) {
return div(v1, v2, DEFAUT_DIV_SCALE);
return div(v1, v2, DEFAULT_DIV_SCALE);
}
/**
@ -528,7 +528,7 @@ public class NumberUtil {
* @return 两个参数的商
*/
public static double div(Double v1, Double v2) {
return div(v1, v2, DEFAUT_DIV_SCALE);
return div(v1, v2, DEFAULT_DIV_SCALE);
}
/**
@ -540,7 +540,7 @@ public class NumberUtil {
* @since 3.1.0
*/
public static BigDecimal div(Number v1, Number v2) {
return div(v1, v2, DEFAUT_DIV_SCALE);
return div(v1, v2, DEFAULT_DIV_SCALE);
}
/**
@ -551,7 +551,7 @@ public class NumberUtil {
* @return 两个参数的商
*/
public static BigDecimal div(String v1, String v2) {
return div(v1, v2, DEFAUT_DIV_SCALE);
return div(v1, v2, DEFAULT_DIV_SCALE);
}
/**

View File

@ -14,14 +14,7 @@ import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.net.*;
import java.nio.charset.Charset;
import java.util.Map;
import java.util.jar.JarFile;
@ -669,9 +662,11 @@ public class URLUtil {
/**
* 标准化URL字符串包括
*
* <pre>
* 1. 多个/替换为一个
* </pre>
* <ol>
* <li>自动补齐http://</li>
* <li>去除开头的\或者/</li>
* <li>替换\/</li>
* </ol>
*
* @param url URL字符串
* @return 标准化后的URL字符串
@ -683,9 +678,11 @@ public class URLUtil {
/**
* 标准化URL字符串包括
*
* <pre>
* 1. 多个/替换为一个
* </pre>
* <ol>
* <li>自动补齐http://</li>
* <li>去除开头的\或者/</li>
* <li>替换\/</li>
* </ol>
*
* @param url URL字符串
* @param isEncodePath 是否对URL中path部分的中文和特殊字符做转义不包括 http:, /和域名部分
@ -693,6 +690,26 @@ public class URLUtil {
* @since 4.4.1
*/
public static String normalize(String url, boolean isEncodePath) {
return normalize(url, isEncodePath, false);
}
/**
* 标准化URL字符串包括
*
* <ol>
* <li>自动补齐http://</li>
* <li>去除开头的\或者/</li>
* <li>替换\/</li>
* <li>如果replaceSlash为true则替换多个/为一个</li>
* </ol>
*
* @param url URL字符串
* @param isEncodePath 是否对URL中path部分的中文和特殊字符做转义不包括 http:, /和域名部分
* @param replaceSlash 是否替换url body中的 //
* @return 标准化后的URL字符串
* @since 5.5.5
*/
public static String normalize(String url, boolean isEncodePath, boolean replaceSlash) {
if (StrUtil.isBlank(url)) {
return url;
}
@ -718,10 +735,12 @@ public class URLUtil {
// 去除开头的\或者/
//noinspection ConstantConditions
body = body.replaceAll("^[\\\\/]+", StrUtil.EMPTY);
// 替换多个\/单个/
// 替换\/
body = body.replace("\\", "/");
//issue#I25MZL双斜杠在URL中是允许存在的不做替换
//.replaceAll("//+", "/");
if (replaceSlash) {
//issue#I25MZL@Gitee双斜杠在URL中是允许存在的默认不做替换
body = body.replaceAll("//+", "/");
}
}
final int pathSepIndex = StrUtil.indexOf(body, '/');

View File

@ -563,6 +563,7 @@ public class ZipUtil {
* 获取压缩包中的指定文件流
*
* @param zipFile 压缩文件
* @param charset 编码
* @param path 需要提取文件的文件名或路径
* @return 压缩文件流如果未找到返回{@code null}
* @since 5.5.2

View File

@ -384,4 +384,11 @@ public class FileUtilTest {
File file2 = new File("d:/test2/aaa");
Assert.assertFalse(FileUtil.isSub(file, file2));
}
@Test
public void isSubRelativeTest() {
File file = new File("..");
File file2 = new File(".");
Assert.assertTrue(FileUtil.isSub(file, file2));
}
}

View File

@ -0,0 +1,14 @@
package cn.hutool.core.io;
import cn.hutool.core.io.resource.ResourceUtil;
import org.junit.Assert;
import org.junit.Test;
public class IoUtilTest {
@Test
public void readBytesTest(){
final byte[] bytes = IoUtil.readBytes(ResourceUtil.getStream("hutool.jpg"));
Assert.assertEquals(22807, bytes.length);
}
}

View File

@ -1,5 +1,6 @@
package cn.hutool.core.io.file;
import org.junit.Assert;
import org.junit.Ignore;
import org.junit.Test;
@ -33,4 +34,10 @@ public class PathUtilTest {
public void moveTest(){
PathUtil.move(Paths.get("d:/lombok.jar"), Paths.get("d:/test/"), false);
}
@Test
public void getMimeTypeTest(){
final String mimeType = PathUtil.getMimeType(Paths.get("d:/test/test.jpg"));
Assert.assertEquals("image/jpeg", mimeType);
}
}

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-cron</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-crypto</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-db</artifactId>

View File

@ -19,6 +19,12 @@ import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;
/**
* 提供基于方言的原始增删改查执行封装
*
* @author looly
* @since 5.5.3
*/
public class DialectRunner implements Serializable {
private static final long serialVersionUID = 1L;
@ -47,6 +53,7 @@ public class DialectRunner implements Serializable {
}
//---------------------------------------------------------------------------- CRUD start
/**
* 批量插入数据<br>
* 批量插入必须严格保持Entity的结构一致不一致会导致插入数据出现不可预知的结果<br>
@ -65,7 +72,7 @@ public class DialectRunner implements Serializable {
PreparedStatement ps = null;
try {
if(1 == records.length){
if (1 == records.length) {
//单条单独处理
ps = dialect.psForInsert(conn, records[0]);
return new int[]{ps.executeUpdate()};
@ -83,8 +90,9 @@ public class DialectRunner implements Serializable {
* 插入数据<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接
* @param record 记录
* @param <T> 主键类型可能为数字或对象列表
* @param conn 数据库连接
* @param record 记录
* @param generatedKeysHandler 自增主键处理器用于定义返回自增主键的范围和类型
* @return 主键列表
* @throws SQLException SQL执行异常
@ -99,7 +107,7 @@ public class DialectRunner implements Serializable {
try {
ps = dialect.psForInsert(conn, record);
ps.executeUpdate();
if(null == generatedKeysHandler){
if (null == generatedKeysHandler) {
return null;
}
return StatementUtil.getGeneratedKeys(ps, generatedKeysHandler);
@ -204,10 +212,10 @@ public class DialectRunner implements Serializable {
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param <T> 结果对象类型
* @param conn 数据库连接对象
* @param <T> 结果对象类型
* @param conn 数据库连接对象
* @param query 查询条件包含表名
* @param rsh 结果集处理对象
* @param rsh 结果集处理对象
* @return 结果对象
* @throws SQLException SQL执行异常
*/

View File

@ -153,7 +153,7 @@ public class SqlConnRunner extends DialectRunner {
* @throws SQLException SQL执行异常
*/
public Long insertForGeneratedKey(Connection conn, Entity record) throws SQLException {
return insert(conn, record, (rs)->{
return insert(conn, record, (rs) -> {
Long generatedKey = null;
if (rs != null && rs.next()) {
try {
@ -281,7 +281,7 @@ public class SqlConnRunner extends DialectRunner {
/**
* 获取查询结果总数生成类似于 SELECT count(1) from (sql)
*
* @param conn 数据库连接对象
* @param conn 数据库连接对象
* @param selectSql 查询语句
* @return 结果数
* @throws SQLException SQL异常
@ -322,7 +322,7 @@ public class SqlConnRunner extends DialectRunner {
*/
public PageResult<Entity> page(Connection conn, SqlBuilder sqlBuilder, Page page) throws SQLException {
final PageResultHandler pageResultHandler = new PageResultHandler(
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int)count(conn, sqlBuilder.build())),
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int) count(conn, sqlBuilder.build())),
this.caseInsensitive);
return page(conn, sqlBuilder, page, pageResultHandler);
}
@ -370,7 +370,7 @@ public class SqlConnRunner extends DialectRunner {
*/
public PageResult<Entity> page(Connection conn, Collection<String> fields, Entity where, Page page) throws SQLException {
final PageResultHandler pageResultHandler = new PageResultHandler(
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int)count(conn, where)),
new PageResult<>(page.getPageNumber(), page.getPageSize(), (int) count(conn, where)),
this.caseInsensitive);
return page(conn, fields, where, page, pageResultHandler);
}
@ -379,10 +379,11 @@ public class SqlConnRunner extends DialectRunner {
* 分页查询<br>
* 此方法不会关闭Connection
*
* @param conn 数据库连接对象
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类包含表名
* @param page 分页对象
* @param <T> 结果类型取决于 {@link RsHandler} 的处理逻辑
* @param conn 数据库连接对象
* @param fields 返回的字段列表null则返回所有字段
* @param where 条件实体类包含表名
* @param page 分页对象
* @param handler 结果集处理器
* @return 结果对象
* @throws SQLException SQL执行异常

View File

@ -7,7 +7,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-dfa</artifactId>

View File

@ -98,6 +98,7 @@ public class WordTree extends HashMap<Character, WordTree> {
* 添加单词使用默认类型
*
* @param word 单词
* @return this
*/
public WordTree addWord(String word) {
final Filter<Character> charFilter = this.charFilter;

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-extra</artifactId>

View File

@ -70,6 +70,7 @@ public class GanymedUtil {
* @param cmd 命令
* @param charset 发送和读取内容的编码
* @param errStream 错误信息输出到的位置
* @return 执行返回结果
*/
public static String exec(Session session, String cmd, Charset charset, OutputStream errStream) {
final String result;
@ -97,6 +98,7 @@ public class GanymedUtil {
* @param cmd 命令
* @param charset 发送和读取内容的编码
* @param errStream 错误信息输出到的位置
* @return 执行返回结果
*/
public static String execByShell(Session session, String cmd, Charset charset, OutputStream errStream) {
final String result;

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-http</artifactId>

View File

@ -1008,6 +1008,17 @@ public class HttpRequest extends HttpBase<HttpRequest> {
return proxyAuth(HttpUtil.buildBasicAuth(username, password, charset));
}
/**
* 令牌验证生成的头类似于"Authorization: Bearer XXXXX"一般用于JWT
*
* @param token 令牌内容
* @return HttpRequest
* @since 5.5.3
*/
public HttpRequest bearerAuth(String token) {
return auth("Bearer " + token);
}
/**
* 验证简单插入Authorization头
*
@ -1094,9 +1105,9 @@ public class HttpRequest extends HttpBase<HttpRequest> {
}
/**
* 调用转发如果需要转发返回转发结果否则返回<code>null</code>
* 调用转发如果需要转发返回转发结果否则返回{@code null}
*
* @return {@link HttpResponse}无转发返回 <code>null</code>
* @return {@link HttpResponse}无转发返回 {@code null}
*/
private HttpResponse sendRedirectIfPossible() {
if (this.maxRedirectCount < 1) {

View File

@ -404,7 +404,7 @@ public class HttpUtil {
*/
private static HttpResponse requestDownloadFile(String url, File destFile, int timeout) {
Assert.notBlank(url, "[url] is blank !");
Assert.notNull(url, "[destFile] is null !");
Assert.notNull(destFile, "[destFile] is null !");
final HttpResponse response = HttpRequest.get(url).timeout(timeout).executeAsync();
if (response.isOk()) {

View File

@ -4,14 +4,13 @@ import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import cn.hutool.http.HttpUtil;
import cn.hutool.http.ssl.SSLSocketFactoryBuilder;
import cn.hutool.json.JSONUtil;
import org.junit.Ignore;
import org.junit.Test;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@ -144,4 +143,25 @@ public class HttpRequestTest {
Console.log(execute.body());
}
@Test
public void getByProxy(){
System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");
// 用户名密码, 若已添加白名单则不需要添加
final String ProxyUser = "t10757311156848";
final String ProxyPass = "ikm5uu44";
Authenticator.setDefault(new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(ProxyUser, ProxyPass.toCharArray());
}
});
final HttpResponse res = HttpRequest.get("https://httpbin.org/get")
.basicAuth(ProxyUser, ProxyPass)
.setHttpProxy("tps193.kdlapi.com", 15818).execute();
Console.log(res.body());
}
}

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-json</artifactId>

View File

@ -74,7 +74,7 @@ final class InternalJSONUtil {
* 缩进使用空格符
*
* @param writer writer
* @param indent 进空格数
* @param indent 进空格数
* @throws IOException IO异常
*/
protected static void indent(Writer writer, int indent) throws IOException {

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-log</artifactId>

View File

@ -8,7 +8,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-poi</artifactId>

View File

@ -1,13 +1,19 @@
package cn.hutool.poi.ofd;
import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.io.file.PathUtil;
import org.ofdrw.font.Font;
import org.ofdrw.layout.OFDDoc;
import org.ofdrw.layout.edit.Annotation;
import org.ofdrw.layout.element.Div;
import org.ofdrw.layout.element.Img;
import org.ofdrw.layout.element.Paragraph;
import org.ofdrw.reader.OFDReader;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.nio.file.Path;
@ -28,7 +34,7 @@ public class OfdWriter implements Serializable, Closeable {
*
* @param file 生成的文件
*/
public OfdWriter(File file){
public OfdWriter(File file) {
this(file.toPath());
}
@ -37,8 +43,16 @@ public class OfdWriter implements Serializable, Closeable {
*
* @param file 生成的文件
*/
public OfdWriter(Path file){
this.doc = new OFDDoc(file);
public OfdWriter(Path file) {
try {
if(PathUtil.exists(file, true)){
this.doc = new OFDDoc(new OFDReader(file), file);
} else{
this.doc = new OFDDoc(file);
}
} catch (IOException e) {
throw new IORuntimeException(e);
}
}
/**
@ -46,20 +60,20 @@ public class OfdWriter implements Serializable, Closeable {
*
* @param out 需要输出的流
*/
public OfdWriter(OutputStream out){
public OfdWriter(OutputStream out) {
this.doc = new OFDDoc(out);
}
/**
* 增加文本内容
*
* @param font 字体
* @param font 字体
* @param texts 文本
* @return this
*/
public OfdWriter addText(Font font, String... texts){
public OfdWriter addText(Font font, String... texts) {
final Paragraph paragraph = new Paragraph();
if(null != font){
if (null != font) {
paragraph.setDefaultFont(font);
}
for (String text : texts) {
@ -69,15 +83,62 @@ public class OfdWriter implements Serializable, Closeable {
}
/**
* 增加节点
* 追加图片
*
* @param picFile 图片文件
* @param width 宽度
* @param height 高度
* @return this
*/
public OfdWriter addPicture(File picFile, int width, int height) {
return addPicture(picFile.toPath(), width, height);
}
/**
* 追加图片
*
* @param picFile 图片文件
* @param width 宽度
* @param height 高度
* @return this
*/
public OfdWriter addPicture(Path picFile, int width, int height) {
final Img img;
try {
img = new Img(width, height, picFile);
} catch (IOException e) {
throw new IORuntimeException(e);
}
return add(img);
}
/**
* 增加节点
*
* @param div 节点可以是段落CanvasImg或者填充
* @return this
*/
public OfdWriter add(Div div){
public OfdWriter add(Div div) {
this.doc.add(div);
return this;
}
/**
* 增加注释比如水印等
*
* @param page 页码
* @param annotation 节点可以是段落CanvasImg或者填充
* @return this
*/
public OfdWriter add(int page, Annotation annotation) {
try {
this.doc.addAnnotation(page, annotation);
} catch (IOException e) {
throw new IORuntimeException(e);
}
return this;
}
@Override
public void close() {
IoUtil.close(this.doc);

View File

@ -8,7 +8,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-script</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-setting</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-socket</artifactId>

View File

@ -9,7 +9,7 @@
<parent>
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
</parent>
<artifactId>hutool-system</artifactId>

View File

@ -8,7 +8,7 @@
<groupId>cn.hutool</groupId>
<artifactId>hutool-parent</artifactId>
<version>5.5.3-SNAPSHOT</version>
<version>5.5.5-SNAPSHOT</version>
<name>hutool</name>
<description>Hutool是一个小而全的Java工具类库通过静态方法封装降低相关API的学习成本提高工作效率使Java拥有函数式语言般的优雅让Java语言也可以“甜甜的”。</description>
<url>https://github.com/looly/hutool</url>