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)文章
使用java反射將結(jié)果集封裝成為對(duì)象和對(duì)象集合操作
這篇文章主要介紹了使用java反射將結(jié)果集封裝成為對(duì)象和對(duì)象集合操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-08-08Spring Boot集成Swagger接口分類與各元素排序問(wèn)題
這篇文章主要介紹了Spring Boot集成Swagger接口分類與各元素排序問(wèn)題,首先我們需要對(duì)Swagger中的接口也就是以Controller 層作為第一級(jí)梯度進(jìn)行組織的,Controller在我們實(shí)際開(kāi)發(fā)中,與其他具體接口之間是存在一對(duì)多的關(guān)系,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10解決Mybatis 大數(shù)據(jù)量的批量insert問(wèn)題
這篇文章主要介紹了解決Mybatis 大數(shù)據(jù)量的批量insert問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-01-01Java基礎(chǔ)高級(jí)綜合練習(xí)題撲克牌的創(chuàng)建
今天小編就為大家分享一篇關(guān)于Java基礎(chǔ)高級(jí)綜合練習(xí)題撲克牌的創(chuàng)建,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-01-01Java C++題解leetcode1620網(wǎng)絡(luò)信號(hào)最好的坐標(biāo)
這篇文章主要為大家介紹了Java C++題解leetcode1620網(wǎng)絡(luò)信號(hào)最好的坐標(biāo)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01springMVC?MultipartFile上傳圖片時(shí)如何修改圖片大小
這篇文章主要介紹了springMVC?MultipartFile上傳圖片時(shí)如何修改圖片大小問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-12-12Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析
這篇文章主要介紹了Java的Struts框架中配置國(guó)際化的資源存儲(chǔ)的要點(diǎn)解析,針對(duì)用戶所使用的語(yǔ)言來(lái)配置資源文件,需要的朋友可以參考下2016-04-04