This commit is contained in:
Looly 2024-09-07 20:04:36 +08:00
parent c74e244959
commit 1fa1b5f173
5 changed files with 97 additions and 35 deletions

View File

@ -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编码的内容
@ -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<br>
* 对于网络流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;
}
}

View File

@ -16,6 +16,8 @@
package org.dromara.hutool.core.io.buffer;
import org.dromara.hutool.core.io.IoUtil;
/**
* 代码移植自<a href="https://github.com/biezhi/blade">blade</a><br>
* 快速缓冲将数据存放在缓冲集中取代以往的单一数组
@ -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);
}

View File

@ -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}对象<br>
* 如果输入流的长度不确定
*
* @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);
}
/**

View File

@ -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;
}
/**

View File

@ -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<Integer> 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;
}
/**
* 从流中读取对象即对象的反序列化
*