溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Java中的字節(jié)和字符輸入流的簡(jiǎn)單介紹

發(fā)布時(shí)間:2021-07-28 09:05:26 來(lái)源:億速云 閱讀:111 作者:chen 欄目:開(kāi)發(fā)技術(shù)

本篇內(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)在下面

    字節(jié)輸出流OutputStream

    對(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ì)了;

    字節(jié)輸入流InputStream

    同樣,這貨也是一個(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)吧,也別愣著了,碼代碼唄;

    字符輸入流Reader

    那些啥抽象啊,子類(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)題;

    字節(jié)流和字符流的區(qū)別

    通過(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í)用文章!

    向AI問(wèn)一下細(xì)節(jié)

    免責(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)容。

    AI