diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b7c1cd2c..dec1188f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Changelog +------------------------------------------------------------------------------------------------------------- + +# 5.5.4 (2020-12-16) + +### 新特性 +### Bug修复 +* 【core 】 修复IoUtil.readBytes的问题 + + ------------------------------------------------------------------------------------------------------------- # 5.5.3 (2020-12-11) diff --git a/README-EN.md b/README-EN.md index 472d6b799..de675a27d 100644 --- a/README-EN.md +++ b/README-EN.md @@ -125,19 +125,19 @@ Each module can be introduced individually, or all modules can be introduced by cn.hutool hutool-all - 5.5.3 + 5.5.4 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.5.3' +compile 'cn.hutool:hutool-all:5.5.4' ``` ## 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.4/) +- [Maven2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.4/) > note: > Hutool 5.x supports JDK8+ and is not tested on Android platforms, and cannot guarantee that all tool classes or tool methods are available. diff --git a/README.md b/README.md index 76d6ef33f..5663dd161 100644 --- a/README.md +++ b/README.md @@ -123,21 +123,21 @@ Hutool的存在就是为了减少代码搜索成本,避免网络上参差不 cn.hutool hutool-all - 5.5.3 + 5.5.4 ``` ### Gradle ``` -compile 'cn.hutool:hutool-all:5.5.3' +compile 'cn.hutool:hutool-all:5.5.4' ``` ### 非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.4/) +- [Maven中央库2](http://repo2.maven.org/maven2/cn/hutool/hutool-all/5.5.4/) > 注意 > Hutool 5.x支持JDK8+,对Android平台没有测试,不能保证所有工具类或工具方法可用。 diff --git a/bin/version.txt b/bin/version.txt index d4e50692a..c8f1d098d 100755 --- a/bin/version.txt +++ b/bin/version.txt @@ -1 +1 @@ -5.5.3 +5.5.4 diff --git a/docs/js/version.js b/docs/js/version.js index f133da001..44b8b9b87 100644 --- a/docs/js/version.js +++ b/docs/js/version.js @@ -1 +1 @@ -var version = '5.5.3' \ No newline at end of file +var version = '5.5.4' \ No newline at end of file diff --git a/hutool-all/pom.xml b/hutool-all/pom.xml index 8c3103403..537d1e97f 100644 --- a/hutool-all/pom.xml +++ b/hutool-all/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.3 + 5.5.4 hutool-all diff --git a/hutool-aop/pom.xml b/hutool-aop/pom.xml index 4b1c5e526..5f0a36be5 100644 --- a/hutool-aop/pom.xml +++ b/hutool-aop/pom.xml @@ -9,7 +9,7 @@ cn.hutool hutool-parent - 5.5.3 + 5.5.4 hutool-aop diff --git a/hutool-bloomFilter/pom.xml b/hutool-bloomFilter/pom.xml index 712cda75d..cac489419 100644 --- a/hutool-bloomFilter/pom.xml +++ b/hutool-bloomFilter/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.3 + 5.5.4 hutool-bloomFilter diff --git a/hutool-bom/pom.xml b/hutool-bom/pom.xml index 4b721b72f..969b22b13 100644 --- a/hutool-bom/pom.xml +++ b/hutool-bom/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.3 + 5.5.4 hutool-bom diff --git a/hutool-cache/pom.xml b/hutool-cache/pom.xml index 49ed9b7f9..e1ee87553 100644 --- a/hutool-cache/pom.xml +++ b/hutool-cache/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.3 + 5.5.4 hutool-cache diff --git a/hutool-captcha/pom.xml b/hutool-captcha/pom.xml index 8f52eeaf5..1e1d08f19 100644 --- a/hutool-captcha/pom.xml +++ b/hutool-captcha/pom.xml @@ -7,7 +7,7 @@ cn.hutool hutool-parent - 5.5.3 + 5.5.4 hutool-captcha diff --git a/hutool-core/pom.xml b/hutool-core/pom.xml index 5417ec209..deccd861e 100644 --- a/hutool-core/pom.xml +++ b/hutool-core/pom.xml @@ -17,7 +17,7 @@ cn.hutool hutool-parent - 5.5.3 + 5.5.4 hutool-core diff --git a/hutool-core/src/main/java/cn/hutool/core/codec/Base64.java b/hutool-core/src/main/java/cn/hutool/core/codec/Base64.java index 5aa6ea320..e7843be05 100644 --- a/hutool-core/src/main/java/cn/hutool/core/codec/Base64.java +++ b/hutool-core/src/main/java/cn/hutool/core/codec/Base64.java @@ -14,17 +14,17 @@ import java.nio.charset.Charset; * Base64工具类,提供Base64的编码和解码方案
* base64编码是用64(2的6次方)个ASCII字符来表示256(2的8次方)个ASCII字符,
* 也就是三位二进制数组经过编码后变为四位的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 { /** * 编码为Base64,URL安全的 - * - * @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
- * 如果isMultiLine为true,则每76个字符一个换行符,否则在一行显示 - * - * @param arr 被编码的数组 + * 如果isMultiLine为{@code true},则每76个字符一个换行符,否则在一行显示 + * + * @param arr 被编码的数组 * @param isMultiLine 在76个char之后是CRLF还是EOF - * @param isUrlSafe 是否使用URL安全字符,一般为false + * @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 */ diff --git a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java index 6feba0a8f..ce5bbcc82 100644 --- a/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/io/IoUtil.java @@ -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()}方法可用的流。
* 在Socket通信流中,服务端未返回数据情况下{@link InputStream#available()}方法始终为{@code 0}
* 因此,在读取前需要调用{@link InputStream#read()}读取一个字节(未返回会阻塞),一旦读取到了,{@link InputStream#available()}方法就正常了。
+ * 需要注意的是,在网络流中,是按照块来传输的,所以 {@link InputStream#available()} 读取到的并非最终长度,而是此次块的长度。
* 此方法返回对象的规则为: * *