最近項(xiàng)目中有用到io流,由于這部分基礎(chǔ)不牢,所以重新學(xué)習(xí)。
介紹
什么是io流?
流的分按兩種方式進(jìn)行分類:
- 以流的方向進(jìn)行分類
我們的文件保存在硬盤上,從硬盤到內(nèi)存的過程,叫做輸入(Input)。
從內(nèi)存到硬盤上的過程,叫做輸出(Output)。
- 按照讀取數(shù)據(jù)的不同進(jìn)行分類
有的流是按照字節(jié)的方式讀取數(shù)據(jù)。一次讀取1個(gè)字節(jié)的byte。等同于一次讀取8個(gè)二進(jìn)制位。這種流式萬能的,什么都可以讀取,文件、圖片、音樂...
有的流式按照字符的方式讀取數(shù)據(jù)的。但是只能讀取普通的純文本文件,word文件也無法讀?。‘?dāng)讀取純文本文件時(shí),每次都讀取一個(gè)字符,不管是中文還是英文都讀取一個(gè)字符。而如果按字節(jié)流,中文一個(gè)字要讀取兩遍才可以。
我們需要注意,java中的char字符底層是占用兩個(gè)字節(jié)的,而一個(gè)英文字母在windows中是占用一個(gè)子杰,但是在java中就是一個(gè)char。
綜上所述
- 輸入流、輸出流
- 字節(jié)流、字符流
四大家族
四個(gè)抽象類:
java.io.InputStream 字節(jié)輸入流
java.io.OutputStream 字節(jié)輸出流
java.io.Reader 字符輸入流
java.io.Writer 字符輸出流
四個(gè)抽象類都實(shí)現(xiàn)了java.io.Closeable,都有close方法, 我們在使用的時(shí)候,應(yīng)該養(yǎng)成一個(gè)良好的習(xí)慣,流畢竟是一個(gè)通道(內(nèi)存與硬盤的通道),所以我們在使用結(jié)束后一定要關(guān)閉,不然就會(huì)占用很多資源。
同時(shí),我們需要知道所有的輸出流都實(shí)現(xiàn)了java.io.Flushable接口,都是可以刷新的,都含有flush方法。養(yǎng)成好習(xí)慣,我們輸出流在最終輸出之后,一定要使用flush進(jìn)行刷新下,表示當(dāng)前管道的未輸出的數(shù)據(jù)強(qiáng)行輸出完,這樣可以保證我們的的數(shù)據(jù)不會(huì)丟失!
另外:在java中,以stream結(jié)尾的class都是字節(jié)流。以Reader/Writer結(jié)尾的都是字符流。
FileInputStream
- 文件字節(jié)的輸入流,萬能的,任何類型的文件都可以按照這個(gè)流進(jìn)行讀取。
- 字節(jié)的方式,完成輸入的操作,完成讀的操作。
/**
* @author szw<szw0814 @ 1 6 3 . com> 2020/11/29
*/
public class FileInputStreamTest {
@Test
public void readFile(){
FileInputStream f = null;
try {
f = new FileInputStream("E:\\test.txt");
int read = f.read();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
f.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
以上的代碼需要注意幾個(gè)問題:
- 在new FileInputStream時(shí)有參構(gòu)造中填寫的是文件位置,可以是相對路徑,也可以是絕對路徑。
- 相對路徑是相對與該項(xiàng)目
- 路徑中如果含有‘\’字符,需要進(jìn)行轉(zhuǎn)義,如果是‘/’,則不需要
- 一次read只能讀取一個(gè)字符,讀到結(jié)束時(shí),會(huì)返回-1
/**
* @author szw<szw0814 @ 1 6 3 . com> 2020/11/29
*/
public class FileInputStreamTest {
@Test
public void readFile(){
FileInputStream f = null;
try {
f = new FileInputStream("E:\\test.txt");
byte[] bytes = new byte[4];
int readCount = 0;
while ((readCount = f.read(bytes)) != -1){
System.out.print(new String(bytes,0,readCount));
}
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
f.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
我們知道,String類型的底層就是char數(shù)組,我們可以進(jìn)行通過char數(shù)組new String類型。
f.readCount返回的是讀取的長度。當(dāng)讀取長度為-1時(shí)就代表讀取到末尾了。
補(bǔ)充兩個(gè)方法
int available(); // 返回流中當(dāng)前有多少?zèng)]有讀取到的字節(jié)數(shù)量
long skip(long n); // 跳過幾個(gè)字節(jié)不讀
我們在剛剛的案例中是創(chuàng)建一個(gè)長度為4的char數(shù)組,其實(shí)我們有了available方法,我們就可以直接拿到數(shù)組的大小,但是注意文件不可以很大。
?