From 1fa1b5f173b144cbbfaa38f42384f327b77a0637 Mon Sep 17 00:00:00 2001 From: Looly Date: Sat, 7 Sep 2024 20:04:36 +0800 Subject: [PATCH] fix code --- .../org/dromara/hutool/core/io/IoUtil.java | 40 ++++++++++++----- .../hutool/core/io/buffer/FastByteBuffer.java | 6 ++- .../io/stream/FastByteArrayOutputStream.java | 25 ++++++++++- .../core/io/stream/LimitedInputStream.java | 17 +++++-- .../hutool/core/io/stream/StreamReader.java | 44 ++++++++++++------- 5 files changed, 97 insertions(+), 35 deletions(-) diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/IoUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/IoUtil.java index b8dfee7a9..1af33f6ca 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/IoUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/IoUtil.java @@ -67,7 +67,7 @@ import java.util.Objects; */ public class IoUtil extends NioUtil { - // region -------------------------------------------------------------------------------------- Copy + // region ----- Copy /** * 将Reader中的内容复制到Writer中 使用默认缓存大小,拷贝后不关闭Reader @@ -197,9 +197,9 @@ public class IoUtil extends NioUtil { return FileChannelCopier.of().copy(in, out); } - // endregion -------------------------------------------------------------------------------------- Copy + // endregion ----- Copy - // region -------------------------------------------------------------------------------------- toReader and toWriter + // region ----- toReader and toWriter /** * 获得一个文件读取器,默认使用 UTF-8 编码 @@ -274,9 +274,9 @@ public class IoUtil extends NioUtil { return new OutputStreamWriter(out, charset); } } - // endregion -------------------------------------------------------------------------------------- toReader and toWriter + // endregion ----- toReader and toWriter - // region -------------------------------------------------------------------------------------- read + // region ----- read /** * 从流中读取UTF8编码的内容 @@ -423,7 +423,7 @@ public class IoUtil extends NioUtil { * @param acceptClasses 读取对象类型 * @return 输出流 * @throws IORuntimeException IO异常 - * @throws HutoolException ClassNotFoundException包装 + * @throws HutoolException ClassNotFoundException包装 */ public static T readObj(final InputStream in, final Class... acceptClasses) throws IORuntimeException, HutoolException { return StreamReader.of(in, false).readObj(acceptClasses); @@ -513,9 +513,9 @@ public class IoUtil extends NioUtil { } } - // endregion -------------------------------------------------------------------------------------- read + // endregion ----- read - // region -------------------------------------------------------------------------------------- toStream + // region ----- toStream /** * String 转为UTF-8编码的字节流流 @@ -806,9 +806,9 @@ public class IoUtil extends NioUtil { return pushbackInputStream; } - // endregion -------------------------------------------------------------------------------------- toStream + // endregion ----- toStream - // region ----------------------------------------------------------------------------------------------- write + // region -------------- write /** * 将byte[]写到流中,并关闭目标流 @@ -882,7 +882,7 @@ public class IoUtil extends NioUtil { public static void writeObjects(final OutputStream out, final boolean isCloseOut, final Object... contents) throws IORuntimeException { StreamWriter.of(out, isCloseOut).writeObjs(contents); } - // endregion ----------------------------------------------------------------------------------------------- write + // endregion -------------- write /** * 从缓存中刷出数据 @@ -1099,4 +1099,22 @@ public class IoUtil extends NioUtil { throw new IORuntimeException(e); } } + + /** + * 获取流长度,对于文件流,会调用{@link FileInputStream#available()}方法,对于其他流,返回-1
+ * 对于网络流,available可能为分段大小,所以返回-1 + * + * @param in 流 + * @return 长度,-1表示未知长度 + */ + public static int length(final InputStream in) { + if (in instanceof FileInputStream) { + try { + return in.available(); + } catch (final IOException e) { + throw new IORuntimeException(e); + } + } + return -1; + } } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/buffer/FastByteBuffer.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/buffer/FastByteBuffer.java index 099240cc1..210ff2281 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/buffer/FastByteBuffer.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/buffer/FastByteBuffer.java @@ -16,6 +16,8 @@ package org.dromara.hutool.core.io.buffer; +import org.dromara.hutool.core.io.IoUtil; + /** * 代码移植自blade
* 快速缓冲,将数据存放在缓冲集中,取代以往的单一数组 @@ -59,7 +61,7 @@ public class FastByteBuffer { * 构造 */ public FastByteBuffer() { - this(1024); + this(IoUtil.DEFAULT_BUFFER_SIZE); } /** @@ -69,7 +71,7 @@ public class FastByteBuffer { */ public FastByteBuffer(int size) { if (size <= 0) { - size = 1024; + size = IoUtil.DEFAULT_BUFFER_SIZE; } this.minChunkLen = Math.abs(size); } diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/FastByteArrayOutputStream.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/FastByteArrayOutputStream.java index 741923f0d..ee94c06dd 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/FastByteArrayOutputStream.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/FastByteArrayOutputStream.java @@ -16,12 +16,14 @@ package org.dromara.hutool.core.io.stream; -import org.dromara.hutool.core.io.buffer.FastByteBuffer; import org.dromara.hutool.core.io.IORuntimeException; +import org.dromara.hutool.core.io.IoUtil; +import org.dromara.hutool.core.io.buffer.FastByteBuffer; import org.dromara.hutool.core.util.CharsetUtil; import org.dromara.hutool.core.util.ObjUtil; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.nio.charset.Charset; @@ -38,13 +40,32 @@ import java.nio.charset.Charset; */ public class FastByteArrayOutputStream extends OutputStream { + /** + * 根据输入流的总长度创建一个{@code FastByteArrayOutputStream}对象
+ * 如果输入流的长度不确定,且 + * + * @param in 输入流 + * @param limit 限制大小 + * @return {@code FastByteArrayOutputStream} + */ + public static FastByteArrayOutputStream of(final InputStream in, final int limit) { + int length = IoUtil.length(in); + if (length < 0 || length > limit) { + length = limit; + } + if (length < 0) { + length = IoUtil.DEFAULT_BUFFER_SIZE; + } + return new FastByteArrayOutputStream(length); + } + private final FastByteBuffer buffer; /** * 构造 */ public FastByteArrayOutputStream() { - this(1024); + this(IoUtil.DEFAULT_BUFFER_SIZE); } /** diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LimitedInputStream.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LimitedInputStream.java index ef0e72955..25dbecdbb 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LimitedInputStream.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/LimitedInputStream.java @@ -16,6 +16,7 @@ package org.dromara.hutool.core.io.stream; +import org.dromara.hutool.core.io.IoUtil; import org.dromara.hutool.core.lang.Assert; import java.io.FilterInputStream; @@ -32,6 +33,16 @@ public class LimitedInputStream extends FilterInputStream { protected long limit; private final boolean throwWhenReachLimit; + /** + * 构造 + * + * @param in {@link InputStream} + * @param limit 限制最大读取量,单位byte + */ + public LimitedInputStream(final InputStream in, final long limit) { + this(in, limit, true); + } + /** * 构造 * @@ -47,7 +58,7 @@ public class LimitedInputStream extends FilterInputStream { @Override public int read() throws IOException { - final int data = (limit == 0) ? -1 : super.read(); + final int data = (limit == 0) ? IoUtil.EOF : super.read(); checkLimit(data); limit = (data < 0) ? 0 : limit - 1; return data; @@ -55,7 +66,7 @@ public class LimitedInputStream extends FilterInputStream { @Override public int read(final byte[] b, final int off, final int len) throws IOException { - final int length = (limit == 0) ? -1 : super.read(b, off, len > limit ? (int) limit : len); + final int length = (limit == 0) ? IoUtil.EOF : super.read(b, off, len > limit ? (int) limit : len); checkLimit(length); limit = (length < 0) ? 0 : limit - length; return length; @@ -72,7 +83,7 @@ public class LimitedInputStream extends FilterInputStream { @Override public int available() throws IOException { final int length = super.available(); - return length > limit ? (int)limit : length; + return length > limit ? (int) limit : length; } /** diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/StreamReader.java b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/StreamReader.java index 33be1dd57..ca670eb70 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/StreamReader.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/io/stream/StreamReader.java @@ -20,9 +20,9 @@ import org.dromara.hutool.core.exception.HutoolException; import org.dromara.hutool.core.io.IORuntimeException; import org.dromara.hutool.core.io.IoUtil; -import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.util.function.Predicate; /** * {@link InputStream}读取器 @@ -102,21 +102,7 @@ public class StreamReader { */ public FastByteArrayOutputStream read(final int limit) throws IORuntimeException { final InputStream in = this.in; - final FastByteArrayOutputStream out; - if (in instanceof FileInputStream) { - // 文件流的长度是可预见的,此时直接读取效率更高 - try { - int length = in.available(); - if (limit > 0 && limit < length) { - length = limit; - } - out = new FastByteArrayOutputStream(length); - } catch (final IOException e) { - throw new IORuntimeException(e); - } - } else { - out = new FastByteArrayOutputStream(); - } + final FastByteArrayOutputStream out = FastByteArrayOutputStream.of(in, limit); try { IoUtil.copy(in, out, IoUtil.DEFAULT_BUFFER_SIZE, limit, null); } finally { @@ -127,6 +113,30 @@ public class StreamReader { return out; } + /** + * 从流中读取内容,直到遇到给定token满足{@link Predicate#test(Object)} + * + * @param predicate 读取结束条件, {@link Predicate#test(Object)}返回true表示结束 + * @return 输出流 + * @throws IORuntimeException IO异常 + */ + public FastByteArrayOutputStream readTo(final Predicate predicate) throws IORuntimeException { + final InputStream in = this.in; + final FastByteArrayOutputStream out = FastByteArrayOutputStream.of(in, -1); + int read; + try { + while ((read = in.read()) > 0) { + if (null != predicate && predicate.test(read)) { + break; + } + out.write(read); + } + } catch (final IOException e) { + throw new IORuntimeException(e); + } + return out; + } + /** * 从流中读取对象,即对象的反序列化 * @@ -142,7 +152,7 @@ public class StreamReader { * @param acceptClasses 读取对象类型 * @return 输出流 * @throws IORuntimeException IO异常 - * @throws HutoolException ClassNotFoundException包装 + * @throws HutoolException ClassNotFoundException包装 */ @SuppressWarnings("unchecked") public T readObj(final Class... acceptClasses) throws IORuntimeException, HutoolException {