字节流--IO学习笔记(二)
IO流:
包括字節(jié)流和字符流。
在這里解釋一下我對(duì)于流的理解,其實(shí)流就相當(dāng)于一個(gè)用來(lái)運(yùn)輸字節(jié)或者字符的管道,一開(kāi)始會(huì)把所有的數(shù)據(jù)存放到流中,然后我們?cè)購(gòu)牧髦腥〕鰯?shù)據(jù)(進(jìn)行讀取或者寫(xiě)出操作),每讀或者寫(xiě)一次就會(huì)從管道中把讀或者寫(xiě)的數(shù)據(jù)取出來(lái),管道中就沒(méi)有了你剛才讀到或者寫(xiě)出的數(shù)據(jù)了。比如:
FileInputStream fis = new FileInputStream(String filename);
就會(huì)把文件名為filename的文件內(nèi)容全部存放到管道中去,然后我們進(jìn)行fis.read(),就會(huì)從管道中讀取出內(nèi)容,讀到的內(nèi)容就會(huì)從管道中消失。
字節(jié)流:
(1)InputStream:抽象了應(yīng)用程序讀取數(shù)據(jù)的方式
OutputStream : 抽象了應(yīng)用程序?qū)懗鰯?shù)據(jù)的方式
(2)輸入流的基本方法:
InputStream in = new InputStream();
int b = in.read();
讀取一個(gè)字節(jié)無(wú)符號(hào)填充到int的最后8位,返回的是讀到的字節(jié)(轉(zhuǎn)換成int類(lèi)型的值的)內(nèi)容,當(dāng)讀到-1時(shí),標(biāo)識(shí)讀取到最后結(jié)束了。
in.read(byte[] buf):讀取的數(shù)據(jù)填充到字節(jié)數(shù)組buf中,返回的是讀到的字節(jié)的個(gè)數(shù)。
in.read(byte[] buf,int start ,int size):讀取數(shù)據(jù)到字節(jié)數(shù)組buf,并且是從buf的start位置開(kāi)始,最多存放size長(zhǎng)度的數(shù)據(jù),返回的是讀到的字節(jié)的個(gè)數(shù)。
(3)輸出流的基本方法:
OutputStream out = new OutputStream();
out.write(int b):寫(xiě)出一個(gè)字節(jié)到流,寫(xiě)的是int的最后的8位
out.write(byte[] buf):將buf字節(jié)數(shù)組都寫(xiě)入到流
out.write(byte[] buf,int start,int size):字節(jié)數(shù)組buf從start位置開(kāi)始寫(xiě)size長(zhǎng)度的字節(jié)到流
下面介紹字節(jié)流基本的讀取方法的使用(注意:FileInputStream繼承了InputStream)
package com.test.FileInputStream;import java.io.FileInputStream; import java.io.IOException;public class FileInputStreamTest {public static void main(String[] args) {try {System.out.println("方式一:字節(jié)數(shù)組的長(zhǎng)度足夠存儲(chǔ)讀取的內(nèi)容");ReadFile1("C:\\Users\\Administrator\\Desktop\\javaIO\\讀取的測(cè)試文件.txt");System.out.println();System.out.println("方式二:字節(jié)數(shù)組的長(zhǎng)度不足以存儲(chǔ)讀取的內(nèi)容");ReadFile2("C:\\Users\\Administrator\\Desktop\\javaIO\\讀取的測(cè)試文件.txt");} catch (IOException e) {e.printStackTrace();}}/*** 當(dāng)字節(jié)數(shù)組的大小足夠存儲(chǔ)讀取的內(nèi)容的時(shí)候* 只讀取一次,然后打印出來(lái)就可以了*/public static void ReadFile1(String filename) throws IOException{FileInputStream fis = new FileInputStream(filename);byte[] buf = new byte[1024];//從fis中批量讀取字節(jié),放入到buf這個(gè)字節(jié)數(shù)組中, //從第0個(gè)位置開(kāi)始放,最多放buf.length個(gè) //返回的是讀到的字節(jié)的個(gè)數(shù)int bytes = fis.read(buf, 0, buf.length);int j = 1;for(int i=0;i<bytes;i++){//byte類(lèi)型8位,int類(lèi)型32位,為了避免數(shù)據(jù)轉(zhuǎn)換錯(cuò)誤,通過(guò)&0xff將高24位清零System.out.print(Integer.toHexString(buf[i]&0xff)+" ");if(j++%10==0){//每讀取10個(gè)字節(jié)就換行System.out.println();}}fis.close();}/*** 當(dāng)數(shù)組的大小沒(méi)法存儲(chǔ)讀取的全部的字節(jié)的時(shí)候,* 就要對(duì)該字節(jié)數(shù)組進(jìn)行重復(fù)利用,* 每讀取字節(jié)數(shù)組的長(zhǎng)度的內(nèi)容的時(shí)候就打印出來(lái),* 然后再次讀取該字節(jié)數(shù)組長(zhǎng)度的內(nèi)容,* 直到把所有的內(nèi)容讀取出來(lái)*/public static void ReadFile2(String filename) throws IOException{FileInputStream fis = new FileInputStream(filename);byte[] buf = new byte[1024];int bytes = 0;int j = 1;while((bytes = fis.read(buf, 0, buf.length))!=-1){//如果數(shù)組不是足夠大,要進(jìn)行多次的讀取操作for(int i = 0;i<bytes;i++){System.out.print(Integer.toHexString(buf[i]&0xff)+" ");if(j++%10==0){System.out.println();}}}fis.close();} }讀取的文件內(nèi)容:
讀取結(jié)果截圖:
下面對(duì)比下單字節(jié)讀取與批量讀取文件的效率:
所以,批量讀取,對(duì)于大文件而言效率高,也是我們最常見(jiàn)的讀文件的方式。單字節(jié)讀取不適合大文件,大文件讀取的效率很低。
下面介紹字節(jié)流基本的寫(xiě)出方法的使用(注意:FileOutputStream繼承了OutputStream,實(shí)現(xiàn)了向文件中寫(xiě)出byte數(shù)據(jù)的方法)
package com.test.FileOutputStream;import java.io.FileOutputStream; import java.io.IOException;public class FileOutputStreamTest {public static void main(String[] args) {try {WriteFile("C:\\Users\\Administrator\\Desktop\\javaIO\\寫(xiě)入測(cè)試文件.txt");} catch (IOException e) {e.printStackTrace();}}public static void WriteFile(String filename) throws IOException{//如果該文件不存在,則直接創(chuàng)建,如果存在,刪除后創(chuàng)建FileOutputStream fos = new FileOutputStream(filename); // //如果該文件不存在,則直接創(chuàng)建,如果存在,直接在文件中追加內(nèi)容 // FileOutputStream fos = new FileOutputStream(filename,true);/** 寫(xiě)一個(gè)字符的方法(可以寫(xiě)一個(gè)字符)*/fos.write('A');//寫(xiě)出了‘A’的字節(jié)所占位的最后八位fos.write('B');/** 寫(xiě)一個(gè)整數(shù)的方法*/int i = 10;//write()方法只能寫(xiě)八位,那么寫(xiě)一個(gè)int需要寫(xiě)4次,每次8位fos.write(i>>>24);fos.write(i>>>16);fos.write(i>>>8);fos.write(i);/**寫(xiě)一個(gè)字節(jié)數(shù)組的方法 (可以直接寫(xiě)一個(gè)字節(jié)數(shù)組)*/byte[] gbk = "小灰灰".getBytes("gbk");fos.write(gbk);fos.close();}}基本的字節(jié)輸入流和字節(jié)輸出流的整合運(yùn)用:(以Copy文件為例)
package com.test.FileOutputStream;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException;public class CopyFile {public static void main(String[] args) {File srcFile = new File("C:\\Users\\Administrator\\Desktop\\javaIO\\被copy的文件.txt");File destFile = new File("C:\\Users\\Administrator\\Desktop\\javaIO\\copy的文件.txt");try {copyFile(srcFile, destFile);} catch (IOException e) {e.printStackTrace();}}public static void copyFile(File srcFile,File destFile) throws IOException{if(!srcFile.exists()){throw new IllegalArgumentException("文件:"+srcFile+"不存在");}if(!srcFile.isFile()){throw new IllegalArgumentException(srcFile+"不是文件");}FileInputStream fis = new FileInputStream(srcFile);FileOutputStream fos = new FileOutputStream(destFile);byte[] buf = new byte[3*1024];int i;while((i = fis.read(buf,0,buf.length))!=-1){fos.write(buf, 0, i);fos.flush();}fis.close();fos.close();}}DataOutputStream/DataInputStream的使用:
作用:
對(duì)“流”功能的擴(kuò)展,可以更加方便的讀取int,long,字符等基本類(lèi)型的數(shù)據(jù)。
構(gòu)造方法:
DataOutputStream dos = new DataOutputStream(OutputStream out);
DataInputStream dis = new DataInputStream(InputStream in);
從構(gòu)造方法中可以看到這兩種流就是對(duì)普通流進(jìn)行了包裝,方便讀取基本類(lèi)型的數(shù)據(jù)。
DataOutputStream多出來(lái)的寫(xiě)出的方法:
writeInt()
writeDouble()
writeLong()
writeChars()//采用UTF-16BE編碼寫(xiě)出
writeUTF()//采用UTF-8編碼寫(xiě)出
……
writeInt():
write()方法一次只可以寫(xiě)出最后的8位,但是int類(lèi)型的數(shù)據(jù)是32位(4個(gè)字節(jié)),所以要write()四次才能寫(xiě)出一個(gè)int類(lèi)型的數(shù)據(jù)。
這是我們寫(xiě)一個(gè)int類(lèi)型數(shù)據(jù)的方法。
writeInt()方法可以只寫(xiě)一次就可以寫(xiě)出一個(gè)int類(lèi)型的數(shù)據(jù),其實(shí)查看源碼可以知道其實(shí)也是write()了四次。
writeInt()方法的源碼:
writeLong(),writeDouble()……也是這樣的原理。
所以可以看出DataOutputStream就是對(duì)基本類(lèi)型的數(shù)據(jù)的寫(xiě)出方法進(jìn)行了包裝,方便我們寫(xiě)出基本類(lèi)型的數(shù)據(jù)。
BufferedInputStream/BufferedOutputStream的使用:
這兩個(gè)流為IO提供了帶緩沖區(qū)的操作,一般打開(kāi)文件進(jìn)行寫(xiě)入或者讀取操作時(shí),都會(huì)加上緩沖,這種流模式提高了IO的性能。
解釋:
從應(yīng)用程序中把數(shù)據(jù)放入文件,相當(dāng)于將一缸水倒入另一個(gè)缸中。
FileOutputStream—–>write()方法相當(dāng)于一滴水一滴水的把水轉(zhuǎn)過(guò)去
DataOutputStream—>writeXxx()方法會(huì)方便一些,相當(dāng)于一瓢一瓢的轉(zhuǎn)移過(guò)去
BufferedOutputStream—>write()方法更方便,相當(dāng)于一瓢一瓢先放入桶中,再?gòu)耐爸械谷氲搅韨€(gè)缸中,性能提高了。
注意:當(dāng)使用BufferedOutputStream的時(shí)候,當(dāng)寫(xiě)完一次后要進(jìn)行沖刷緩沖區(qū)(flush()),否則下次進(jìn)行寫(xiě)入的時(shí)候就沒(méi)法向緩沖區(qū)中存放了。
下面比較一下這些流讀取和寫(xiě)入操作的效率:
所用時(shí)間結(jié)果截圖:
由此可以看出:
批量讀取文件的效率>字符緩沖流讀取文件的效率>單字節(jié)讀取文件的效率
總結(jié)
以上是生活随笔為你收集整理的字节流--IO学习笔记(二)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 文件编码和RandomAccessFil
- 下一篇: 字符流---IO学习笔记(三)