inputstream java_Java实现inputstream流的复制
獲取到一個inputstream后,可能要多次利用它進行read的操作。由于流讀過一次就不能再讀了,而InputStream對象本身不能復制,而且它也沒有實現(xiàn)Cloneable接口,所以得想點辦法。
實現(xiàn)思路:
1、先把InputStream轉化成ByteArrayOutputStream
2、后面要使用InputStream對象時,再從ByteArrayOutputStream轉化回來
代碼實現(xiàn)如下:
package com.test;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
public class StreamOperateUtil {
public static void main(String[] args) throws FileNotFoundException {
InputStream input = new FileInputStream("c:\\test.txt");
//InputStream input = httpconn.getInputStream(); //這里可以寫你獲取到的流
ByteArrayOutputStream baos = cloneInputStream(input);
// 打開兩個新的輸入流
InputStream stream1 = new ByteArrayInputStream(baos.toByteArray());
InputStream stream2 = new ByteArrayInputStream(baos.toByteArray());
}
private static ByteArrayOutputStream cloneInputStream(InputStream input) {
try {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = input.read(buffer)) > -1) {
baos.write(buffer, 0, len);
}
baos.flush();
return baos;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
}
這種適用于一些不是很大的流,因為緩存流是會消耗內(nèi)存的。
關于InputStream為什么不能被重復讀取?
首先,熟悉Java的人可能都知道,Java中的Inputstream是不能重復讀取的。
但是有沒有想過,InputStream為什么不能重復讀呢?
其實要回答“為什么”這個問題很簡單,就是人家接口就是這么設計的,不能重復讀。
所以今天要討論的問題更像是:Java的InputStream為什么要設計為不能重復讀?
關于InputStream為什么不能重復讀取,網(wǎng)上也各有說法:
有的同學說:
“InputStream就類比成一個杯子,杯子里的水就像InputStream里的數(shù)據(jù),你把杯子里的水拿出來了,杯子的水就沒有了,InputStream也是同樣的道理。”
比喻的非常好,讓我們從直觀上認識了InputStream為什么不能重復被讀。
也有的同學從更深的代碼角度去分析:
“在InputStream讀取的時候,會有一個pos指針,他指示每次讀取之后下一次要讀取的起始位置,當讀到最后一個字符的時候,pos指針不會重置。”
說的也有道理,就是說InputStream的讀取是單向的。但是并不是所有的InputStream實現(xiàn)類都是這樣的實現(xiàn)方式。
//BufferedInputStream代碼片段:
public synchronized int read() throws IOException {
if (pos >= count) {
fill();
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff;
}
//FileInputStream代碼片段:
public native int read() throws IOException;
我們知道:
Java 的List內(nèi)部是使用數(shù)組實現(xiàn)的,遍歷的時候也有一個pos指針。但是沒有說List遍歷一個第二次遍歷就沒有了。第二次遍歷是創(chuàng)建新的Iterator,所以pos也回到了數(shù)組起始位置。對于某些InputStream當然可以也這么做。例如:ByteArrayInputStream
ByteArrayInputStream就是將一個Java的byte數(shù)組保存到對象里,然后讀取的時候遍歷該byte數(shù)組。
public ByteArrayInputStream(byte buf[]) {
this.buf = buf;
this.pos = 0;
this.count = buf.length;
}
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
就ByteArrayInputStream而言,要實現(xiàn)重復讀取是很簡單的,但是為什么沒有。我想是為了遵循InputStream的統(tǒng)一標準。
在InputStream的read方法的注釋上明確說明:
/**
* Reads the next byte of data from the input stream. The value byte is
* returned as an int in the range 0 to
* 255. If no byte is available because the end of the stream
* has been reached, the value -1 is returned. This method
* blocks until input data is available, the end of the stream is detected,
* or an exception is thrown.
*
*
A subclass must provide an implementation of this method.
*
* @return the next byte of data, or -1 if the end of the
* stream is reached.
* @exception IOException if an I/O error occurs.
*/
public abstract int read() throws IOException;
當流到達末尾后,返回-1.
其實像FileInputStream這樣的文件流,要實現(xiàn)重復使用可能也并不是很難,利用緩存什么的應該能做到(大文件讀取就悲劇了,呵呵呵)。
但是InputStream顧名思義就是一個單向的字節(jié)流,跟水流一樣,要想再次使用就自己再去源頭取一下。
InputStream其實不像杯子,更像是一根水管,要想喝水了,就在把水管架在水源與杯子之間,讓水流到杯子里(注意:這個動作完成了之后水管里面就沒有水了)。
這樣看來,InputStream其實是一個數(shù)據(jù)通道,只負責數(shù)據(jù)的流通,并不負責數(shù)據(jù)的處理和存儲等其他工作范疇。
前面講過,其實有的InputStream實現(xiàn)類是可以實現(xiàn)數(shù)據(jù)的處理工作的。但是沒有這么做,這就是規(guī)范和標準的重要性。
創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎總結
以上是生活随笔為你收集整理的inputstream java_Java实现inputstream流的复制的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: 京东黄金和博时黄金的区别,划重点啦!
- 下一篇: 债券型基金收益如何?债券型基金理财技巧
