1.IO流
以后開發(fā)中會遇到文件的上傳和下載益缠,都是需要用到IO流
咱們電腦上面所有的文件贬养, 文檔 音頻 圖片 視頻 等都是可以進行讀和寫的权烧。他們咋讀的翠肘? 咋寫的檐束?
依靠流的形式進行讀 和寫。很抽象
在讀取的時候束倍,會將咱們的文件(音頻 視頻 等)變成流的形式 一點一點來處理的 拆解開來處理的被丧。
1.1緩沖的概念
看視頻有點卡盟戏?暫停一下,加載緩沖一下甥桂。
快遞:送到物流中轉(zhuǎn)站柿究,然后分批次的發(fā)。物流中轉(zhuǎn)站就是緩沖的概念黄选。
IO流 的本質(zhì)就是對電腦的文件進行讀和寫的
計算機通過CPU內(nèi)存讀取磁盤上面的文件數(shù)據(jù)蝇摸,假如一次讀取1字節(jié)。但是可以加上緩沖的概念办陷,每次讀取4字節(jié)(4kb)貌夕。效率會高點的。
1.2IO流的分類
1.從磁盤讀取數(shù)據(jù)到內(nèi)存(Java代碼) 磁盤>>代碼中????輸入流
2.從內(nèi)存(Java代碼 )寫入到磁盤某一個文件 代碼>>磁盤 ????輸出流
參照物:是內(nèi)存民镜,就是Java代碼蜂嗽。 輸入流: 從磁盤讀取到內(nèi)存 輸出流:從內(nèi)存寫入到磁盤
I:
input: 輸入 從磁盤讀取數(shù)據(jù)到內(nèi)存使用input輸入流的應(yīng)用場景是啥:比如 磁盤上面有一個1.txt文件,將1.txt文件的內(nèi)容讀取到Java內(nèi)存中殃恒。使用的就是輸入流植旧。
輸入流分為兩種:
1.字節(jié)輸入流 FileInputStream(重點)
2.字符輸入流 FileRead(非重點)
O:
out:輸出 將java代碼寫入到磁盤中某一個文件
輸出流分為兩種:
1.字節(jié)輸出流 FileOutputStream(重點)
2.字符輸出流 FileWrite(非重點)
1.2.1字節(jié)輸入流
字節(jié)輸入流:磁盤上面有一個1.txt文件,現(xiàn)在要將1.txt文件中的內(nèi)容讀取到內(nèi)存(Java代碼中)
Java給咱們封裝好了類: FileInputStream 文件輸入流(字節(jié)輸入流)
package com.wyx.a_fileinputstream;
import java.io.*;
import java.util.Arrays;
public class Demo1 {
public static void main(String[] args) throws IOException {
//將磁盤上面的e:/aaa/1.txt文檔內(nèi)容讀取到內(nèi)存(java代碼)中
//加上緩沖的效果
//1.創(chuàng)建File對象离唐,是咱們本地磁盤文件的一個file文件
//為啥要創(chuàng)建這個File對象病附?
//因為要讀取1.txt這個文件的里面的內(nèi)容,首先先找到文件再說亥鬓。
File file = new File("e:/aaa/1.txt");
//2.創(chuàng)建文件字節(jié)流輸入對象完沪,來操作1.txt
//FileInputStream(File file)
//通過打開與實際文件的連接創(chuàng)建一個FileInputStream,
//該文件由文件系統(tǒng)中的 File對象 file命名嵌戈。
//該對象作用將c:/aaa/1.txt文件轉(zhuǎn)為字節(jié)輸入流的形式覆积,之后可以按照流的形式讀取到內(nèi)存中
FileInputStream fis = new FileInputStream(file);
//3.fileInputStream 這個流本身不具備緩沖的效果。
//但是要加上緩沖的效果J烨骸?淼怠! 咋辦庵朝?使用另外一個流
//BufferedInputStream
//一個 BufferedInputStream 為另一個輸入流添加了功能吗冤,即緩沖輸入。
//咋加九府?將FileInputStream傳給BufferedInputStream
//此時FileInputStream 就具備緩沖的功能了W滴痢!侄旬!
BufferedInputStream bis = new BufferedInputStream(fis);
//使用字節(jié)緩沖流操作1.txt文件
//當創(chuàng)建BufferedInputStream時肺蔚,
//將創(chuàng)建一個內(nèi)部緩沖區(qū)數(shù)組,這個數(shù)組是什么數(shù)據(jù)類型的?
//byte 為啥是byte類型的數(shù)組
//因為是字節(jié)輸入流 所以是byte byte 就是字節(jié)
//4.創(chuàng)建一個緩沖區(qū)的數(shù)組
byte[] buf = new byte[4 * 1024];//緩沖區(qū):可以存放4096字節(jié)
//現(xiàn)在數(shù)組是空的
//5.讀取數(shù)據(jù)
//public int read(byte[] b)
// throws IOException
//從輸入流讀取一些字節(jié)數(shù)儡羔,并將它們存儲到緩沖區(qū)b 宣羊。
// 實際讀取的字節(jié)數(shù)作為整數(shù)返回
//如果b的長度為零声旺,就是輸出容量為0,則不會讀取字節(jié)并返回0 ;
// 否則段只,嘗試讀取至少一個字節(jié)。
// 如果沒有字節(jié)可用鉴扫,因為流在文件末尾赞枕,則返回值-1
//將1.txt文件的內(nèi)容 讀取到緩沖數(shù)組中buf里面
//之前buf是一個空的數(shù)組,現(xiàn)在通過read方法將1.txt文件中的內(nèi)容讀取到了 buf空的數(shù)組中,返回是int類型的實際讀取字節(jié)數(shù)
// int read = bis.read(buf);
// System.out.println("實際讀取字節(jié)數(shù)" + read);//6
//借助String查看存的內(nèi)容坪创,因為是數(shù)組炕婶,無法直接打印。從0開始莱预,打印前6個柠掂,因為文檔中只存了6個字節(jié)內(nèi)容,所以打印前6個字節(jié)
// System.out.println(new String(buf, 0, read));
//當緩沖數(shù)組的容量小于文件字節(jié)數(shù)的時候依沮,
//發(fā)現(xiàn)數(shù)據(jù)一次性讀取不完涯贞?咋辦?咋解決危喉?
//倆種思想:
//一是多讀取幾遍宋渔,不使用,文檔大的時候辜限,重復(fù)代碼多
// int read1 = bis.read(buf);
// System.out.println(new String(buf, 0, read1));
// int read2 = bis.read(buf);
// System.out.println(new String(buf, 0, read2));
//二:借助循環(huán)
int length = -1;
//如果length=-1 那么就會到達流的末尾 就證明后面沒有數(shù)據(jù)
//循環(huán)結(jié)束皇拣,不要再讀了
while ((length = bis.read(buf)) != -1) {
//數(shù)組中的東西要展示出來 使用String
//將磁盤上面的內(nèi)容 讀取到 >> 內(nèi)存 buf數(shù)組中
System.out.println(new String(buf, 0, length));
}
//6.是需要關(guān)閉的(要不然占內(nèi)存)
//關(guān)閉緩沖流
bis.close();
//關(guān)閉輸入流
fis.close();
}
}
字節(jié)輸入流入門案例
package com.wyx.a_fileinputstream;
import java.io.*;
public class Demo2 {
public static void main(String[] args) throws IOException {
//對哪個文件操作,先找到這個文件
File file = new File("e:/aaa/2.txt");
//創(chuàng)建輸入流對象
FileInputStream fis = new FileInputStream(file);
//添加緩沖效果
BufferedInputStream bis = new BufferedInputStream(fis);
//讀取到的數(shù)組存到byte數(shù)組中
byte[] but = new byte[1024 * 4];
int length;
while ((length = bis.read(but)) != -1) {
//借助String類將數(shù)組打印出來
System.out.println(new String(but,0, length));
}
//關(guān)閉流
bis.close();
fis.close();
}
}
字節(jié)輸出流(從內(nèi)存到磁盤)write(byte[] b)
write(byte[] b); 寫入到磁盤薄嫡,參數(shù)是一個字節(jié)數(shù)組
將str字符串轉(zhuǎn)為字節(jié)數(shù)組:str.getBytes();
代碼運行一次氧急,會把原先內(nèi)容給覆蓋掉
輸出流:如果發(fā)現(xiàn)發(fā)現(xiàn)文件不存在,不會報錯毫深,因為會自動創(chuàng)建文件吩坝,但不會自動創(chuàng)建目錄,
輸入流:找不到文件會報錯
package com.wyx.a_fileinputstream;
import java.io.*;
public class Demo3 {
public static void main(String[] args) throws IOException {
//1.創(chuàng)建File對象哑蔫,文件路徑對象 告知編譯器要把數(shù)據(jù)寫到哪個文件中
File file = new File("e:/aaa/3.txt");
//2.實例化字節(jié)輸出流對象
FileOutputStream fos = new FileOutputStream(file);
//3.對FileOutputStream 加上緩沖的效果
BufferedOutputStream bos = new BufferedOutputStream(fos);
String str = "五一假期就我自己沒走";
//將str字符串轉(zhuǎn)為字節(jié)數(shù)組
byte[] b = str.getBytes();
bos.write(b);
//5.寫完以后一定要刷新流然后關(guān)閉流
bos.flush();//沒有實際的意義钾恢,可以不寫的
//6.關(guān)閉流
//在輸出流的時候一定是先開的后關(guān),后開的先關(guān)
bos.close();
fos.close();
}
}
write的重載方法:write(int a)開發(fā)時候不用
write(int a);傳的是一個int類型的數(shù)
雖然傳的是int類型的鸳址,但是真正寫入的是int類型所對應(yīng)的ASCLL碼所對應(yīng)的字符
package com.wyx.b_fileoutputstream;
import java.io.*;
public class Demo2 {
public static void main(String[] args) throws IOException {
File file = new File("e:/aaa/4.txt");
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
//void write(int b);
//傳參是一個int類型瘩蚪,但是真正寫入的時候是int類型所對應(yīng)的字符
bos.write(97);//開發(fā)時候不用
bos.flush();
bos.close();
fos.close();
}
}
write的重載方法:write(byte[] b, int off, int len)【重要】(開發(fā)經(jīng)常用)
從指定的字節(jié)數(shù)組中寫入len個字節(jié),從偏移off開始到緩沖的輸出流
如果指定的len長度超過字節(jié)數(shù)組長度稿黍,回報數(shù)組下標越界錯誤
package com.wyx.b_fileoutputstream;
import java.io.*;
public class Demo3 {
public static void main(String[] args) throws IOException {
File file = new File("e:/aaa/4.txt");
FileOutputStream fos = new FileOutputStream(file);
BufferedOutputStream bos = new BufferedOutputStream(fos);
String str = "abcdefg";
//write(byte[] b,int off,int len)
byte[] bytes = str.getBytes();
bos.write(bytes, 0, 2);//寫入的是ab
bos.flush();
bos.close();
fos.close();
}
}
代碼簡寫
package com.wyx.b_fileoutputstream;
import java.io.*;
public class Demo4 {
public static void main(String[] args) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("e:/aaa/4.txt")));
bos.write("寢室就我一個人".getBytes());
bos.flush();
bos.close();
}
}
案例
把E盤aaa文件下的一個視屏復(fù)制到D盤下的aaa文件下
思路:先讀取再寫入
帶緩沖的效果
package com.wyx.b_fileoutputstream;
import java.io.*;
public class Demo5 {
public static void main(String[] args) throws IOException {
//1.創(chuàng)建一個字節(jié)緩沖輸入流
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(new File("e:/aaa/java.mp4")));
//2.創(chuàng)建一個字節(jié)緩沖輸出流,雖然d:/aaa/下面沒有java.mp4這個文件疹瘦,但是不會報錯,他會自動創(chuàng)建
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File("d:/aaa/java.mp4")));
//3.創(chuàng)建緩沖數(shù)組
byte[] bytes = new byte[1024 * 4];
//4.借助循環(huán)讀取和寫入
int length;
while ((length = bis.read(bytes)) != -1) {
bos.write(bytes, 0 ,length);
}
//5.關(guān)閉流
bos.flush();
bis.close();
bos.close();
}
}
不帶緩沖效果
package com.wyx.b_fileoutputstream;
import java.io.*;
public class Demo6 {
public static void main(String[] args) throws IOException {
//獲取當前系統(tǒng)時間
long start = System.currentTimeMillis();
FileInputStream fis = new FileInputStream(new File("c:/bbb/3.mp4"));
FileOutputStream fos = new FileOutputStream(new File("c:/aaa/goudan.mp4"));
int length = -1;
//一次讀取一個字節(jié)
while ((length = fis.read()) != -1) {
fos.write(length);
}
fos.close();
fis.close();
//運行完之后代碼時間
long end = System.currentTimeMillis();
//相減得出代碼運行時間
System.out.println(end - start);
}
}
帶緩沖效果與不帶緩沖新效果相比較巡球,發(fā)現(xiàn)帶緩沖效果好言沐,運行時間短邓嘹,而不帶緩沖效果的,一次只能讀取一個字節(jié)险胰,運行時間長汹押。當然,也并不是緩沖數(shù)組長度越大越好起便,緩沖數(shù)組越大棚贾,在內(nèi)存開辟的空間就越大,占的內(nèi)存就越大榆综。