Input
引出:
File對象是讀取檔案的屬性資料,如果要讀取檔案的内容,則需要IO流技術
IO流分類:
按方向:
————輸入流
————輸出流
按傳輸機關:
————–位元組流: 讀取二進制資料,不經過任何處理
————–字元流: 讀取二進制資料,并轉換成字元
其實就是 位元組流+解碼
①先複習輸入流
所有輸入位元組流的基類————InputStream(抽象類!!)
———————————-FileInputStream 讀取檔案資料的輸入流
怎麼讀?
1. 找到目标檔案
2. 建立資料的輸入通道。
3. 讀取檔案中的資料。
4. **關閉資源.**
找到JDK中的FileInputStream,發現内容并不多,常用的隻有關閉流的close方法和讀取流的read方法。。。。。之前真的是莫名恐懼。

對照着文檔看見read方法,很容易就可以想出讀取檔案資料的方式。
即循環緩沖數組讀出。注意讀取時都是根據讀取長度更新覆寫緩沖數組,不清空!!
public class Demo1 {
public static void main(String[] args) throws IOException {
readTest4();
}
//方式4:使用緩沖數組配合循環一起讀取。28
public static void readTest4() throws IOException{
long startTime = System.currentTimeMillis();
//找到目标檔案
File file = new File("F:\\美女\\1.jpg");
//建立資料的輸入通道
FileInputStream fileInputStream = new FileInputStream(file);
//建立緩沖數組配合循環讀取檔案的資料。
int length = 0; //儲存每次讀取到的位元組個數。
byte[] buf = new byte[1024]; //存儲讀取到的資料 緩沖數組 的長度一般是1024的倍數,因為與計算機的處理機關。 理論上緩沖數組越大,效率越高
while((length = fileInputStream.read(buf))!=-1){ // read方法如果讀取到了檔案的末尾,那麼會傳回-1表示。
System.out.print(new String(buf,0,length));
}
//關閉資源
fileInputStream.close();
long endTime = System.currentTimeMillis();
System.out.println("讀取的時間是:"+ (endTime-startTime)); //446
}
//方式3:使用緩沖 數組 讀取。 缺點: 無法讀取完整一個檔案的資料。 12G
public static void readTest3() throws IOException{
//找到目标檔案
File file = new File("F:\\a.txt");
//建立資料的輸入通道
FileInputStream fileInputStream = new FileInputStream(file);
//建立緩沖位元組數組,讀取檔案的資料。
byte[] buf = new byte[1024]; //相當于超市裡面的購物車。
int length = fileInputStream.read(buf); // 如果使用read讀取資料傳入位元組數組,那麼資料是存儲到位元組數組中的,而這時候read方法的傳回值是表示的是本次讀取了幾個位元組資料到位元組數組中。
System.out.println("length:"+ length);
//使用位元組數組建構字元串
String content = new String(buf,0,length);
System.out.println("内容:"+ content);
//關閉資源
fileInputStream.close();
}
//方式2 : 使用循環讀取檔案的資料
public static void readTest2() throws IOException{
long startTime = System.currentTimeMillis();
//找到目标檔案
File file = new File("F:\\美女\\1.jpg");
//建立資料的輸入通道
FileInputStream fileInputStream = new FileInputStream(file);
//讀取檔案的資料
int content = 0; //聲明該變量用于存儲讀取到的資料
while((content = fileInputStream.read())!=-1){
System.out.print((char)content);
}
//關閉資源
fileInputStream.close();
long endTime = System.currentTimeMillis();
System.out.println("讀取的時間是:"+ (endTime-startTime)); //446
}
//讀取的方式一缺陷: 無法讀取完整一個檔案 的資料.
public static void readTest1() throws IOException{
//1. 找到目标檔案
File file = new File("F:\\a.txt");
//建立資料的輸入通道。
FileInputStream fileInputStream = new FileInputStream(file);
//讀取檔案中的資料
int content = fileInputStream.read(); // read() 讀取一個位元組的資料,把讀取的資料傳回。
System.out.println("讀到的内容是:"+ (char)content);
//關閉資源 實際上就是釋放資源。
fileInputStream.close();
}
}
②後複習輸出流
所有輸出位元組流的基類————OutputStream(抽象類!!)
———————————-FileOutputStream 讀取檔案資料的輸出流
怎麼用??
首先注意構造方法, 第二個是追加輸出
他本身的方法也很垃圾。。。就是write和close。。
FileOutputStream要注意的細節:
1. 使用FileOutputStream 的時候,如果目标檔案不存在,那麼會自動建立目标檔案對象。
2. 使用FileOutputStream寫資料的時候,如果目标檔案已經存在,那麼會先清空目标檔案中的資料,然後再寫入資料。
3.使用FileOutputStream寫資料的時候, 如果目标檔案已經存在,需要在原來資料基礎上追加資料的時候應該使用new FileOutputStream(file,true)構造函數,第二參數為true。
4.使用FileOutputStream的write方法寫資料的時候,雖然接收的是一個int類型的資料,但是真正寫出的隻是一個位元組的資料,隻是把低八位的二進制資料寫出,其他二十四位資料全部丢棄。
緩沖流
顯然用緩沖數組讀取效率高,那麼為什麼非要用普通的輸入輸出流配合自己定義的緩沖數組去實作這個過程呢? 于是引出緩沖流
①緩沖輸入位元組流
BufferInputStream 類, 其實打開源碼看到其實就是内部維護了位元組數組。
首先看他的構造方法:
顯然不是直接建立的緩沖流,不能用一個File類作為參數建立流,而是需要一個普通的輸入流作為參數去建立。。顯然好傻逼阿 - -為啥不設計成直接傳File參數呢- -。。是以其實 緩沖流是不具備讀寫能力的!!!,他的讀寫能力都是通過參數的流的讀寫能力來的。。
注意啊。。InputStream是抽象類。。不能直接建立對象的, 是以要用多态。。傳子類進去。。。
好渣。read方法每次隻能讀一個位元組。。但是為什麼會比普通的輸入流快呢?。。
打開源碼看。。原來是先一個個讀。。然後把讀到的資料存到内部維護的數組中,然後從數組中去取出來列印。。。内部維護的數組什麼概念!!是緩沖流這個對象的成員!! 在堆記憶體中!!! 直接在記憶體中讀取資料,當然比在硬碟中讀快了!!!是以其實跟自己建立一個8kb的緩沖數組是差不多的。。。。。。
public synchronized int read() throws IOException {
if (pos >= count) { //pos 是目前取到了緩沖數組的第幾個位元組, count是讀取了多少個位元組到緩沖數組
fill(); //沒到8kb先一直填充
if (pos >= count)
return -1;
}
return getBufIfOpen()[pos++] & 0xff; //一個一個讀取數組資料。沒讀完前不用讀了。
}
②緩沖輸出位元組流
使用跟輸入流差不多啊。。。也是維護了一個8kb的緩沖數組,寫資料的時候就先寫到緩沖數組裡面。
啥時候寫到檔案中呢??
① 8kb滿了, 自動全寫
②調用flush方法! 沒滿8kb也寫到檔案去!!
但是注意一下他的方法:
他也是有close方法的!!!坑爹API1.6裡面居然沒有。。我要立刻換文檔!!
public void close() throws IOException {
try (OutputStream ostream = out) {
flush();
}
}