其它類:
InputStream/OutputStream:https://blog.csdn.net/sinat_27180253/article/details/82185306
ObjectInputStream/ObjectOutputStream:https://blog.csdn.net/sinat_27180253/article/details/82185460
ByteArrayInputStream/ByteArrayOutputStream:https://blog.csdn.net/sinat_27180253/article/details/82185609
DataInputStream/DataOutputStream:https://blog.csdn.net/sinat_27180253/article/details/82186009
BufferedInputStream
1.類功能簡介
緩衝字節輸入流、作爲FilterInputStream的一個子類、所提供的功能是爲傳入的底層字節輸入流提供緩衝功能、通過底層字節輸入流(in)中的字節讀取到自己的buffer中(內置緩存字節數組)、然後程序調用BufferedInputStream的read方法將buffer中的字節讀取到程序中、當buffer中的字節被讀取完之後、BufferedInputStream會從in中讀取下一個數據塊到buffer中供程序讀取、直到in中數據被讀取完畢、這樣做的好處一是提高了讀取的效率、二是減少了打開存儲介質的連接次數、詳細的原因下面BufferedOutputStream有說到。其有個關鍵的方法fill()就是每當buffer中數據被讀取完之後從in中將數據填充到buffer中、程序從內存中讀取數據的速度是從磁盤中讀取的十倍!這是一個很恐怖的效率的提升、同時我們也不能無禁止的指定BufferedInputStream的buffer大小、畢竟、一次性讀取in中耗時較長、二是內存價格相對昂貴、我們能做的就是儘量在其中找到合理點。一般也不用我們費這個心、創建BufferedInputStream時使用buffer的默認大小就好。
構造方法
- BufferedInputStream (InputStream in); //使用默認buf大小、底層字節輸入流構建bis
- BufferedInputStream (InputStream in, int size); //使用指定buf大小、底層字節輸入流構建bis
一般方法
- int available(); //返回底層流對應的源中有效可供讀取的字節數
- void close(); //關閉此流、釋放與此流有關的所有資源
- boolean markSupport(); //查看此流是否支持mark、此方法一直返回true
- void mark(int readLimit); //標記當前buf中讀取下一個字節的下標
- int read(); //讀取buf中下一個字節
- int read(byte[] b, int off, int len); //讀取buf中下一個字節
- void reset(); //重置最後一次調用mark標記的buf中的位子
- long skip(long n); //跳過n個字節、 不僅僅是buf中的有效字節、也包括in的源中的字節
BufferedOutputStream
1.類功能簡介
BufferedOutputStream:緩存字節輸出流,作爲FilterInputStream的一個子類,爲傳入的底層字節輸出流提供緩存功能,同樣當使用底層字節輸出流向目的地中寫入字節或者字節數組時,沒寫入一次就要打開一次到目的地的連接,這樣頻繁的訪問不斷效率底下,也有可能會對存儲介質造成一定的破壞,比如當我們向磁盤中不斷的寫入字節時,誇張一點,將一個非常大單位是G的字節數據寫入到磁盤的指定文件中的,沒寫入一個字節就要打開一次到這個磁盤的通道,這個結果無疑是恐怖的,而當我們使用BufferedOutputStream將底層字節輸出流,比如FileInputStream包裝一下之後,我們可以在程序中先將要寫入到文件中的字節寫入到BufferedOutputStream的內置緩存空間中,然後當達到一定數量時,一次性寫入FileInputStream流中,此時FileInputStream就可以打開一次通道,將這個數據塊寫入到文件中,這樣做雖然不可能達到一次訪問就將所有數據寫入磁盤中的效果,但也大大提高了效率和減少了磁盤的訪問量!這就是其意義所在。
他的具體工作原理在這裏簡單提一下:當程序中每次將字節或者字節數組寫入到BufferedOutputStream中時,都會檢查BufferedOutputStream中的緩存字節數組buf(buf的大小是默認的或者在創建bos時指定的,一般使用默認的就好)是否存滿,如果沒有存滿則將字節寫入到buf中,如果存滿,則調用底層的writer(byte[] b, int off, int len)將buf中的所有字節一次性寫入到底層out中,如果寫入的是字節數組,如果buf中已滿則同上面滿的時候的處理,如果能夠存下寫入的字節數組,則存入buf中,如果存不下,並且要寫入buf的字節個數小於buf的長度,則將buf中所有字節寫入到out中,然後將要寫入的字節存放到buf中(從下標0開始存放),如果要寫入out中的字節超過buf的長度,則直接寫入out中。
構造方法
- BufferedOutputStream(OutputStream out); //使用默認大小,底層字節輸出流構造bos
- BufferedOutputStream(OutputStream out, int size); //使用指定大小,底層字節輸出流構造bos
一般方法
- void flush(); //將寫入bos中的數據flush到out指定的目的地中,注意這裏不是flush到out中,因爲其內部又調用了out.flush()
- synchronized void close() //關閉
- write(byte b); //將一個字節寫入到buf中
- write(byte[] b, int off, int len); //將b的一部分寫入buf中
package com.stydy.stream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
public class BufferedStream {
// 文件路徑
public static final String filePath = "D:" + File.separator + "ZZ" + File.separator + "stream.txt";
//private static String msg = "大家好大家好大家好大家好大家好大家好大家好大家好大家好大家好!!";
private static String msg = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static void main(String[] args) throws Exception {
//testBufferedOutputStream();
testBufferedInpuStream();
}
public static void testBufferedOutputStream() throws Exception {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(filePath)));
bos.write(msg.getBytes());
//跳過第一個字節
//bos.write(msg.getBytes(), 1, msg.getBytes().length-1);
bos.flush();
}
public static void testBufferedInpuStream() throws Exception {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File(filePath)));
for (int i = 0; i < 10; i++) {
if (bis.available() >= 0) {
System.out.println(byteToString((byte) bis.read()));
}
}
if (!bis.markSupported()) {
return;
}
// 標記"當前索引位子" 即第11個字節 k
bis.mark(6666);
// 丟棄10個字節。
bis.skip(10);
// 讀取剩下的b.length個字節
byte[] b = new byte[1024];
int n1 = bis.read(b, 0, b.length);
System.out.println("剩餘有效字節 : " + n1);
printByteValue(b);
// 重置輸入流最後一次調用mark()標記的索引位置
bis.reset();
int n2 = bis.read(b, 0, b.length);
System.out.println("剩餘有效字節 : " + n2);
printByteValue(b);
}
//輸出字節
private static void printByteValue(byte[] buf) {
for (byte b : buf) {
if (b != 0) {
System.out.print(byteToString(b) + " ");
}
}
}
//字節轉字符
private static String byteToString(byte b) {
byte[] bAray = {b};
return new String(bAray);
}
}
總結
對於BufferedInputStream、BufferedOutputStream、本質就是爲底層字節輸入輸出流添加緩衝功能、先將底層流中的要讀取或者要寫入的數據先以一次讀取一組的形式來講數據讀取或者寫入到buffer中、再對buffer進行操作、這樣不但效率、還能節省資源。最後、在程序中、出於效率的考慮、也應爲低級流使用這兩個類進行裝飾一下。