您好,登錄后才能下訂單哦!
本篇內(nèi)容介紹了“Java中的字節(jié)和字符輸入流的簡(jiǎn)單介紹”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!
字節(jié)輸出流OutputStream
字符輸出流
字節(jié)輸入流InputStream
字符輸入流Reader
字節(jié)流和字符流的區(qū)別
總結(jié)
我先解釋一下什么叫IO流:
I:指的是InputStream,這是一個(gè)抽象類(lèi),最常用的子類(lèi)是FileInputStream
O:值得是OutputStream,這也是一個(gè)抽象類(lèi),最常用的子類(lèi)是OutputStream
流:由于在進(jìn)行文件操作的時(shí)候大多數(shù)是用的byte數(shù)據(jù),這些數(shù)據(jù)并不是一次性寫(xiě)入(讀取),而是像水龍頭那樣慢慢的流(想象一下你接水的場(chǎng)景)
廢話(huà)還是不多bb,先來(lái)一份簡(jiǎn)單的代碼:
File file=new File("e:"+File.separator+"JavaLearn"+File.separator+"EleventhDemo"+File.separator+"1.txt"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); System.out.println("父級(jí)目錄創(chuàng)建成功"); } if (!file.exists()){ file.createNewFile(); }
其中File.separator
指的是當(dāng)前系統(tǒng)的默認(rèn)分隔符,這樣寫(xiě)的原因是可以保證Java文件在Windows系統(tǒng)運(yùn)行時(shí)和Linux系統(tǒng)運(yùn)行時(shí)都不會(huì)出錯(cuò)
這段代碼也很簡(jiǎn)單,主要就是創(chuàng)建一個(gè)文件。
當(dāng)然,這都不是重點(diǎn),重點(diǎn)在下面
對(duì)于Output Stream類(lèi)來(lái)說(shuō),它本身定義的是一個(gè)抽象類(lèi),按照抽象類(lèi)的原則來(lái)講,需要定義抽象類(lèi)的子類(lèi),而我們要執(zhí)行的是文件操作,則可以使用FileOutputStream子類(lèi)來(lái)完成。而我們最關(guān)心的還是子類(lèi)中的構(gòu)造方法
方法 | 描述 |
---|---|
public FileOutputStream(File file) throws FileNotFoundException | 實(shí)例化FileOutputStream,主要用于新建數(shù)據(jù) |
public FileOutputStream(File file,boolean append) throws FileNotFoundException | 實(shí)例化FileOutputStream,主要用于追加數(shù)據(jù) |
我們?cè)趯?shí)例化OutputStream對(duì)象之后肯定要進(jìn)行輸出操作。在OutputStream類(lèi)中定義了3個(gè)輸出方法。例如:
方法 | 描述 |
---|---|
public abstract void write(int b) throws IOException | 輸出單個(gè)字節(jié)數(shù)據(jù) |
public void write(byte[] b) throws IOException | 輸出一組字節(jié)數(shù)據(jù) |
public abstract void write(byte[] b,int off,int len) throws IOException | 輸出部分字節(jié)數(shù)據(jù) |
可能大家在看表的時(shí)候已經(jīng)發(fā)現(xiàn)了,都是byte類(lèi)型的數(shù)據(jù)。
使用OutputStream向文件中輸出數(shù)據(jù)。
import java.io.*; public class test { public static void main(String[] args) throws Exception{ File file=new File("e:"+File.separator+"JavaLearn"+File.separator+"EleventhDemo"+File.separator+"1.txt"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); System.out.println("父級(jí)目錄創(chuàng)建成功"); } if (!file.exists()){ file.createNewFile(); } OutputStream output=new FileOutputStream(file);// 實(shí)例化父類(lèi) String data="Hello World!"; output.write(data.getBytes()); output.close(); } }
可以發(fā)現(xiàn),在文件輸出的過(guò)程中,如果要輸出的文件和目錄不存在那么會(huì)覆蓋掉原有的內(nèi)容,咋辦呢?別忘了我們還有一個(gè)構(gòu)造方法專(zhuān)門(mén)是為了追加數(shù)據(jù)的:
import java.io.*; public class test { public static void main(String[] args) throws Exception{ File file=new File("e:"+File.separator+"JavaLearn"+File.separator+"EleventhDemo"+File.separator+"1.txt"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); System.out.println("父級(jí)目錄創(chuàng)建成功"); } if (!file.exists()){ file.createNewFile(); } OutputStream output=new FileOutputStream(file,true);// 追加數(shù)據(jù) String data="Hello World!"; output.write(data.getBytes()); output.close(); } }
執(zhí)行一遍會(huì)發(fā)現(xiàn),會(huì)自動(dòng)的把數(shù)據(jù)附加在已有的數(shù)據(jù)后面。
我們?cè)趤?lái)看看另一種類(lèi)似的流
看標(biāo)題,字節(jié)和字符就差一個(gè)字,但是,熟悉Java數(shù)據(jù)基本類(lèi)型的都知道。這倆貨一個(gè)是byte,一個(gè)是String。那么我們?cè)趯?duì)文件進(jìn)行輸出操作的時(shí)候,就可以把需要輸出的內(nèi)容定義成String類(lèi)型而不是byte字節(jié)型;
同樣,Writer也是一個(gè)抽象類(lèi),當(dāng)我們用于文件操作的時(shí)候,常用的子類(lèi)就是FileWriter。我們來(lái)看看Writer類(lèi)的常用方法:
方法 | 描述 |
---|---|
public abstract void close() throws IOException | 關(guān)閉輸出流 |
public void write(String str) throws IOException | 將字符串輸出 |
public void write(char[] cbuf) throws IOException | 將字符數(shù)組輸出 |
public abstract void flush() throws IOException | 強(qiáng)制性清空內(nèi)存 |
還是不多bb,上代碼,就知道啥樣子了:
import java.io.*; public class test { public static void main(String[] args) throws Exception{ File file=new File("e:"+File.separator+"JavaLearn"+File.separator+"EleventhDemo"+File.separator+"1.txt"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); System.out.println("父級(jí)目錄創(chuàng)建成功"); } if (!file.exists()){ file.createNewFile(); } Writer out=new FileWriter(file); String data="Hello World!"; out.write(data); out.close(); } }
了解了輸出流,我們?cè)賮?lái)看看輸入流;
Java中的輸入流有兩種,一種是InputStream,另一種就是Reader??催@名字就知道,md,可能又是一種簡(jiǎn)單的一種難的。沒(méi)錯(cuò),你猜對(duì)了;
同樣,這貨也是一個(gè)抽象類(lèi),用于文件操作的也是他的子類(lèi)FileInputStream,當(dāng)然也有幾個(gè)方法用于操作文件:
方法 | 描述 |
---|---|
public abstract int read() throws IOException | 讀取單個(gè)字節(jié)數(shù)據(jù),每次執(zhí)行read()方法都會(huì)讀取一個(gè)數(shù)據(jù)源的指定數(shù)據(jù),如果已經(jīng)讀到了結(jié)尾,則會(huì)返回-1 |
public int read(byte[] b) throws IOException | 讀取多個(gè)字節(jié)數(shù)據(jù),如果要讀取的數(shù)據(jù)小于byte的數(shù)據(jù),這個(gè)時(shí)候read()方法的返回值int返回的是數(shù)據(jù)個(gè)數(shù),如果現(xiàn)在開(kāi)辟的字節(jié)數(shù)組小于讀取的長(zhǎng)度,且數(shù)據(jù)已經(jīng)讀取完了。則這個(gè)時(shí)候返回的是-1 |
public int read(byte[] int off,int len) throws IOException | 讀取指定多個(gè)字節(jié)數(shù)據(jù) |
我們還是看看讀取內(nèi)容,具體代碼怎么去實(shí)現(xiàn)它:
import java.io.*; public class test { public static void main(String[] args) throws Exception{ File file=new File("e:"+File.separator+"JavaLearn"+File.separator+"EleventhDemo"+File.separator+"1.txt"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); System.out.println("父級(jí)目錄創(chuàng)建成功"); } if(file.exists()){ InputStream input=new FileInputStream(file); byte data[] = new byte[1024];// 開(kāi)辟一個(gè)1024長(zhǎng)度的byte數(shù)組 int len=input,read(data); input.close(); System.out.println("讀取的內(nèi)容:"+new String(data,0,lem)); } } }
上述代碼簡(jiǎn)明的表達(dá)了讀取文件的全部?jī)?nèi)容的邏輯,但是想象一下,單個(gè)單個(gè)的讀取怎么做呢?
這時(shí)候需要一點(diǎn)以前的知識(shí)了,看看代碼:
import java.io.*; public class test { public static void main(String[] args) throws Exception{ File file=new File("e:"+File.separator+"JavaLearn"+File.separator+"EleventhDemo"+File.separator+"1.txt"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); System.out.println("父級(jí)目錄創(chuàng)建成功"); } if(file.exists()){ InputStream input=new FileInputStream(file); byte data[] = new data[1024]; int foot=0;// 數(shù)組的索引初始值 int temp=0;// 待會(huì)自己看是啥作用 while((temp=input.read())!=-1){ data[foot++]=(byte) temp; input.close(); System.out.println("讀取到的數(shù)據(jù)是:"+new String(data,0,foot)); } } } }
了解了字節(jié)輸入流,是不是還得了解一下字符輸入流。來(lái)吧,也別愣著了,碼代碼唄;
那些啥抽象啊,子類(lèi)啊啥的我都不說(shuō)了,反正類(lèi)似,自己慢慢琢磨琢磨。
看看有哪些方法:
方法 | 描述 |
---|---|
public abstract void close() throws IOException | 關(guān)閉流 |
public int read() throws IOException | 讀取單個(gè)字符 |
public int read(char[] cbuf) throws IOException | 將內(nèi)容讀到字符數(shù)組中,返回讀入的長(zhǎng)度 |
有一點(diǎn)和上面的不一樣:
雖然Writer類(lèi)中提供了輸出字符串?dāng)?shù)據(jù)的操作方法,但是在Reader類(lèi)中并沒(méi)有這樣的定義。之所以會(huì)這個(gè)樣子,完全是因?yàn)樵谑褂肙utputStream輸出數(shù)據(jù)時(shí),其程序可以輸出的大小一定是程序可以承受的數(shù)據(jù)大小,如果在使用InputStream讀取時(shí),可能被讀取的數(shù)據(jù)灰常大,一次性全部讀取的話(huà)可能會(huì)問(wèn)題,于是就只有一個(gè)一個(gè)的讀取
import java.io.*; public class test { public static void main(String[] args) throws Exception{ File file=new File("e:"+File.separator+"JavaLearn"+File.separator+"EleventhDemo"+File.separator+"1.txt"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); System.out.println("父級(jí)目錄創(chuàng)建成功"); } Reader in=new FileReader(file); char data[] = new char[1024]; int len=in.read(data); in.close(); System.out.println("讀取的內(nèi)容:"+new String(data,0,len)); } }
代碼寫(xiě)了這么一大堆,我們最后再看看一個(gè)問(wèn)題;
通過(guò)以上的代碼演示我們知道了,字節(jié)流和字符流都有類(lèi)似的功能,那么在開(kāi)發(fā)的過(guò)程中具體使用哪一種呢?
他們的區(qū)別在于:
字節(jié)流在進(jìn)行IO操作時(shí),直接針對(duì)的時(shí)操作的數(shù)據(jù)終端(如文件),而字符流操作時(shí)不是直接針對(duì)于終端,而是針對(duì)于緩存區(qū)(理解為內(nèi)存)的操作,而后由緩存區(qū)來(lái)操作終端(如文件),這屬于間接操作,按照這樣的方式,如果在使用字節(jié)流時(shí)不關(guān)閉最后的輸出操作,也可以將所有的內(nèi)容進(jìn)行輸出,而使用字符流時(shí)如果不關(guān)閉,則意味著緩沖區(qū)的內(nèi)容不會(huì)被輸出,當(dāng)然,這個(gè)時(shí)候可以由用戶(hù)自己調(diào)用flush()方法去強(qiáng)制性的手動(dòng)清空 例如:
import java.io.*; public class test { public static void main(String[] args) throws Exception{ File file=new File("e:"+File.separator+"JavaLearn"+File.separator+"EleventhDemo"+File.separator+"1.txt"); if (!file.getParentFile().exists()){ file.getParentFile().mkdirs(); System.out.println("父級(jí)目錄創(chuàng)建成功"); } if (!file.exists()){ file.createNewFile(); } Writer out=new FileWriter(file); String data="Hello World!"; out.write(data); out.flush(); } }
總結(jié)一下,字節(jié)流和字符流的主要區(qū)別:
字節(jié)流沒(méi)有使用到緩沖區(qū),而字符流使用了;
處理各種數(shù)據(jù)都可以通過(guò)字節(jié)流完成,而在處理中午的時(shí)候使用字符流會(huì)更方便;
最后,留一個(gè)思考題給有興趣的小伙伴。
現(xiàn)有一個(gè)要求,按照DOS系統(tǒng)的文件拷貝命令,由初始化參數(shù)輸入源文件和拷貝文件的路徑,而后執(zhí)行操作。
提示:本程序直接在主方法中完成,不考慮多余的方法和類(lèi)的設(shè)計(jì)??紤]大文件的情況(500MB以上)
我把思路也貼給大家:
方案一:將要復(fù)制的文件全部讀取到內(nèi)存中,而后將所有的內(nèi)容一次性輸出到目標(biāo)文件;
方案二:采用邊讀邊寫(xiě)的方式一點(diǎn)一點(diǎn)的進(jìn)行文件的復(fù)制。
“Java中的字節(jié)和字符輸入流的簡(jiǎn)單介紹”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。