Java中InputStream重復(fù)使用問(wèn)題的幾種解決方案
前言
在Java中,InputStream通常設(shè)計(jì)為"一次性"使用,讀取后流會(huì)到達(dá)末尾,再次讀取時(shí)會(huì)返回-1或拋出異常。以下是幾種實(shí)現(xiàn)InputStream重復(fù)使用的方法:
1. 使用mark()和reset()方法(適用于支持標(biāo)記的流)
java
import java.io.*;
public class InputStreamReuser {
public static void main(String[] args) throws IOException {
String data = "Hello World";
InputStream inputStream = new ByteArrayInputStream(data.getBytes());
// 第一次讀取前標(biāo)記
if (inputStream.markSupported()) {
inputStream.mark(0); // 參數(shù)是readlimit,0表示不限制
}
// 第一次讀取
System.out.println("第一次讀取:");
readAndPrint(inputStream);
// 重置流
if (inputStream.markSupported()) {
inputStream.reset();
}
// 第二次讀取
System.out.println("第二次讀取:");
readAndPrint(inputStream);
}
private static void readAndPrint(InputStream is) throws IOException {
int content;
while ((content = is.read()) != -1) {
System.out.print((char) content);
}
System.out.println();
}
}2. 將流內(nèi)容緩存到字節(jié)數(shù)組(最可靠方法)
java
import java.io.*;
public class InputStreamCacher {
public static void main(String[] args) throws IOException {
InputStream originalStream = new FileInputStream("example.txt");
// 將流內(nèi)容緩存到字節(jié)數(shù)組
byte[] bytes = readAllBytes(originalStream);
originalStream.close();
// 創(chuàng)建可重復(fù)使用的流
InputStream reusableStream1 = new ByteArrayInputStream(bytes);
InputStream reusableStream2 = new ByteArrayInputStream(bytes);
// 使用流1
System.out.println("第一次使用:");
readAndPrint(reusableStream1);
// 使用流2
System.out.println("第二次使用:");
readAndPrint(reusableStream2);
}
private static byte[] readAllBytes(InputStream is) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int nRead;
while ((nRead = is.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
}
private static void readAndPrint(InputStream is) throws IOException {
int content;
while ((content = is.read()) != -1) {
System.out.print((char) content);
}
System.out.println();
}
}3. 使用Apache Commons IO的IOUtils(簡(jiǎn)化代碼)
java
import org.apache.commons.io.IOUtils;
import java.io.*;
public class CommonsIOExample {
public static void main(String[] args) throws IOException {
InputStream originalStream = new FileInputStream("example.txt");
// 將流轉(zhuǎn)換為字節(jié)數(shù)組
byte[] bytes = IOUtils.toByteArray(originalStream);
originalStream.close();
// 創(chuàng)建可重復(fù)使用的流
InputStream reusableStream1 = new ByteArrayInputStream(bytes);
InputStream reusableStream2 = new ByteArrayInputStream(bytes);
// 使用流
System.out.println("第一次使用: " + IOUtils.toString(reusableStream1, "UTF-8"));
System.out.println("第二次使用: " + IOUtils.toString(reusableStream2, "UTF-8"));
}
}4. 自定義可重置的InputStream包裝器
java
import java.io.*;
public class ResettableInputStream extends InputStream {
private final InputStream original;
private InputStream current;
private byte[] buffer;
private boolean buffered = false;
public ResettableInputStream(InputStream original) {
this.original = original;
this.current = original;
}
@Override
public int read() throws IOException {
return current.read();
}
public void resetStream() throws IOException {
if (!buffered) {
// 第一次重置時(shí)緩存內(nèi)容
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int nRead;
while ((nRead = original.read(data, 0, data.length)) != -1) {
baos.write(data, 0, nRead);
}
buffer = baos.toByteArray();
buffered = true;
}
current = new ByteArrayInputStream(buffer);
}
@Override
public void close() throws IOException {
original.close();
if (buffered && current != null) {
current.close();
}
}
}
// 使用示例
public class Main {
public static void main(String[] args) throws IOException {
ResettableInputStream ris = new ResettableInputStream(new FileInputStream("example.txt"));
// 第一次讀取
System.out.println("第一次讀取:");
readAndPrint(ris);
// 重置
ris.resetStream();
// 第二次讀取
System.out.println("第二次讀取:");
readAndPrint(ris);
ris.close();
}
private static void readAndPrint(InputStream is) throws IOException {
int content;
while ((content = is.read()) != -1) {
System.out.print((char) content);
}
System.out.println();
}
}注意事項(xiàng)
內(nèi)存考慮:緩存整個(gè)流到內(nèi)存中可能不適合處理非常大的文件
資源釋放:確保在所有使用完成后關(guān)閉流
性能影響:重復(fù)讀取相同的流內(nèi)容會(huì)有額外的內(nèi)存開(kāi)銷
網(wǎng)絡(luò)流:對(duì)于網(wǎng)絡(luò)流,通常無(wú)法重置,必須先緩存內(nèi)容
標(biāo)記支持:不是所有
InputStream實(shí)現(xiàn)都支持mark()和reset()
總結(jié)
到此這篇關(guān)于Java中InputStream重復(fù)使用問(wèn)題的幾種解決方案的文章就介紹到這了,更多相關(guān)Java中InputStream重復(fù)使用內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring aop底層原理及如何實(shí)現(xiàn)
這篇文章主要介紹了spring aop底層原理及如何實(shí)現(xiàn),幫助大家更好的理解和學(xué)習(xí)使用spring aop,感興趣的朋友可以了解下2021-04-04
使用SpringBoot找不到Mapper的Bean問(wèn)題及解決
這篇文章主要介紹了使用SpringBoot找不到Mapper的Bean問(wèn)題及解決,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2026-04-04
eclipse創(chuàng)建java項(xiàng)目并運(yùn)行的詳細(xì)教程講解
eclipse是java開(kāi)發(fā)的ide工具,是大部分java開(kāi)發(fā)人員的首選開(kāi)發(fā)工具,可是對(duì)于一些新Java人員來(lái)說(shuō),不清楚eclipse怎么運(yùn)行項(xiàng)目?這篇文章主要給大家介紹了關(guān)于eclipse創(chuàng)建java項(xiàng)目并運(yùn)行的相關(guān)資料,需要的朋友可以參考下2023-04-04
Java 14 發(fā)布了,你還會(huì)使用Lombok?
2020年3月17日發(fā)布,Java正式發(fā)布了JDK 14 ,目前已經(jīng)可以開(kāi)放下載。在JDK 14中,共有16個(gè)新特性,本文主要來(lái)介紹其中的一個(gè)特性:JEP 359: Records,需要的朋友可以參考下2020-04-04
mybatis參數(shù)類型不匹配錯(cuò)誤argument type mismatch的處理方案
這篇文章主要介紹了mybatis參數(shù)類型不匹配錯(cuò)誤argument type mismatch的處理方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01
mybatis-plus分頁(yè)無(wú)效問(wèn)題解決
本文主要介紹了mybatis-plus分頁(yè)無(wú)效問(wèn)題解決,原因是配置分頁(yè)插件的版本問(wèn)題,舊版本和新版本的MyBatis-Plus需要不同的分頁(yè)配置,感興趣的可以了解一下2025-03-03

