• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            奇奇的空間

            奇奇的空間
            posts - 5, comments - 13, trackbacks - 0, articles - 23

            Java的輸入輸出流

            Posted on 2006-05-08 16:52 奇奇 閱讀(217) 評(píng)論(0)  編輯 收藏 引用 所屬分類: JAVA

            Java語(yǔ)言的輸入輸出功能是十分強(qiáng)大而靈活的,美中不足的是看上去輸入輸出的代碼并不是很簡(jiǎn)潔,因?yàn)槟阃枰b許多不同的對(duì)象。在Java類庫(kù)中,IO部分的內(nèi)容是很龐大的,因?yàn)樗婕暗念I(lǐng)域很廣泛:標(biāo)準(zhǔn)輸入輸出,文件的操作,網(wǎng)絡(luò)上的數(shù)據(jù)流,字符串流,對(duì)象流,zip文件流....本文的目的是為大家做一個(gè)簡(jiǎn)要的介紹。

              流是一個(gè)很形象的概念,當(dāng)程序需要讀取數(shù)據(jù)的時(shí)候,就會(huì)開啟一個(gè)通向數(shù)據(jù)源的流,這個(gè)數(shù)據(jù)源可以是文件,內(nèi)存,或是網(wǎng)絡(luò)連接。類似的,當(dāng)程序需要寫入數(shù)據(jù)的時(shí)候,就會(huì)開啟一個(gè)通向目的地的流。這時(shí)候你就可以想象數(shù)據(jù)好像在這其中“流”動(dòng)一樣,如下圖:


              Java中的流分為兩種,一種是字節(jié)流,另一種是字符流,分別由四個(gè)抽象類來(lái)表示(每種流包括輸入和輸出兩種所以一共四個(gè)):InputStream,OutputStream,Reader,Writer。Java中其他多種多樣變化的流均是由它們派生出來(lái)的:



              在這其中InputStream和OutputStream在早期的Java版本中就已經(jīng)存在了,它們是基于字節(jié)流的,而基于字符流的Reader和Writer是后來(lái)加入作為補(bǔ)充的。以上的層次圖是Java類庫(kù)中的一個(gè)基本的層次體系。

              在這四個(gè)抽象類中,InputStream和Reader定義了完全相同的接口:

            int read()
            int read(char cbuf[])
            int read(char cbuf[], int offset, int length)

              而OutputStream和Writer也是如此:

            int write(int c)
            int write(char cbuf[])
            int write(char cbuf[], int offset, int length)

              這六個(gè)方法都是最基本的,read()和write()通過(guò)方法的重載來(lái)讀寫一個(gè)字節(jié),或者一個(gè)字節(jié)數(shù)組。

              更多靈活多變的功能是由它們的子類來(lái)擴(kuò)充完成的。知道了Java輸入輸出的基本層次結(jié)構(gòu)以后,本文在這里想給大家一些以后可以反復(fù)應(yīng)用例子,對(duì)于所有子類的細(xì)節(jié)及其功能并不詳細(xì)討論。

            import java.io.*;

              public class IOStreamDemo {

              ??????public void samples() throws IOException {

              ???????????//1. 這是從鍵盤讀入一行數(shù)據(jù),返回的是一個(gè)字符串
              ???????????BufferedReader stdin =new BufferedReader(new InputStreamReader(System.in));
              ???????????System.out.print("Enter a line:");
              ???????????System.out.println(stdin.readLine());

              ???????????//2. 這是從文件中逐行讀入數(shù)據(jù)

              ???????????BufferedReader in = new BufferedReader(new FileReader("IOStreamDemo.java"));
              ???????????String s, s2 = new String();
              ???????????while((s = in.readLine())!= null
              ??????????????????????s2 += s + "\n"
              ???????????in.close();

              ???????????//3. 這是從一個(gè)字符串中逐個(gè)讀入字節(jié)
              ???????????StringReader in1 = new StringReader(s2);
              ???????????int c;
              ???????????while((c = in1.read()) != -1)
              ??????????????????????System.out.print((char)c);

              ???????????//4. 這是將一個(gè)字符串寫入文件
              ???????????try {
              ??????????????????????BufferedReader in2 = new BufferedReader(new StringReader(s2));
              ??????????????????????PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out")));
              ??????????????????????int lineCount = 1;
              ??????????????????????while((s = in2.readLine()) != null
              ?????????????????????????????????out1.println(lineCount++ + ": " + s);
              ??????????????????????out1.close();
              ???????????} catch(EOFException e) {
              ??????????????????????System.err.println("End of stream");
              ???????????}
              ??????}

              }

              對(duì)于上面的例子,需要說(shuō)明的有以下幾點(diǎn):

              1. BufferedReaderReader的一個(gè)子類,它具有緩沖的作用,避免了頻繁的從物理設(shè)備中讀取信息。它有以下兩個(gè)構(gòu)造函數(shù):

            BufferedReader Reader in)
            BufferedReaderReader in, int sz)

              這里的sz是指定緩沖區(qū)的大小。

              它的基本方法:

            void close(//關(guān)閉流

            ???????????void mark(int readAheadLimit) //標(biāo)記當(dāng)前位置

            ???????????boolean markSupported() //是否支持標(biāo)記

            ???????????int read() //繼承自Reader的基本方法

            ???????????int read(char[] cbuf, int off,int len) //繼承自Reader的基本方法

            ???????????String readLine() //讀取一行內(nèi)容并以字符串形式返回

            ???????????boolean ready() //判斷流是否已經(jīng)做好讀入的準(zhǔn)備

            ???????????void reset() //重設(shè)到最近的一個(gè)標(biāo)記

            ???????????long skip(long n) //跳過(guò)指定個(gè)數(shù)的字符讀取

              2. InputStreamReaderInputStreamReader之間的橋梁,由于System.in是字節(jié)流,需要用它來(lái)包裝之后變?yōu)樽址鞴┙o ????????????BufferedReader使用。

              3. PrintWriter out1 = new PrintWriter(new BufferedWriter(new FileWriter("IODemo.out")));

              這句話體現(xiàn)了Java輸入輸出系統(tǒng)的一個(gè)特點(diǎn),為了達(dá)到某個(gè)目的,需要包裝好幾層。首先,輸出目的地是文件IODemo.out,所以最內(nèi)層包裝的是FileWriter,建立一個(gè)輸出文件流,接下來(lái),我們希望這個(gè)流是緩沖的,所以用BufferedWriter來(lái)包裝它以達(dá)到目的,最后,我們需要格式化輸出結(jié)果,于是將PrintWriter包在最外層。

              Java提供了這樣一個(gè)功能,將標(biāo)準(zhǔn)的輸入輸出流轉(zhuǎn)向,也就是說(shuō),我們可以將某個(gè)其他的流設(shè)為標(biāo)準(zhǔn)輸入或輸出流,看下面這個(gè)例子:

            import java.io.*;

            public class Redirecting {

            ???????public static void
            main(String[] args) throws IOException {
            ??????????????PrintStream console = System.out;
            ??????????????BufferedInputStream in = newBufferedInputStreamnew FileInputStream"Redirecting.java"));
            ??????????????PrintStream out = newPrintStream( new BufferedOutputStream new FileOutputStream"test.out")));
            ??????????????System.setIn(in);
            ??????????????System.setOut(out);

            ??????????????BufferedReader br = newBufferedReadernewInputStreamReader(System.in));
            ??????????????String s;
            ??????????????while((s = br.readLine()) != null
            ?????????????????????System.out.println(s);
            ??????????????out.close();
            ??????????????System.setOut(console);
            ??????}
            }

              在這里java.lang.System的靜態(tài)方法

            static void setIn(InputStream in)
            static void setOut(PrintStream out)

              提供了重新定義標(biāo)準(zhǔn)輸入輸出流的方法,這樣做是很方便的,比如一個(gè)程序的結(jié)果有很多,有時(shí)候甚至要翻頁(yè)顯示,這樣不便于觀看結(jié)果,這是你就可以將標(biāo)準(zhǔn)輸出流定義為一個(gè)文件流,程序運(yùn)行完之后打開相應(yīng)的文件觀看結(jié)果,就直觀了許多。

              Java流有著另一個(gè)重要的用途,那就是利用對(duì)象流對(duì)對(duì)象進(jìn)行序列化。下面將開始介紹這方面的問題。

              在一個(gè)程序運(yùn)行的時(shí)候,其中的變量數(shù)據(jù)是保存在內(nèi)存中的,一旦程序結(jié)束這些數(shù)據(jù)將不會(huì)被保存,一種解決的辦法是將數(shù)據(jù)寫入文件,而Java中提供了一種機(jī)制,它可以將程序中的對(duì)象寫入文件,之后再?gòu)奈募邪褜?duì)象讀出來(lái)重新建立。這就是所謂的對(duì)象序列化Java中引入它主要是為了RMI(Remote Method Invocation)和Java Bean所用,不過(guò)在平時(shí)應(yīng)用中,它也是很有用的一種技術(shù)。

              所有需要實(shí)現(xiàn)對(duì)象序列化的對(duì)象必須首先實(shí)現(xiàn)Serializable接口。下面看一個(gè)例子:

            import java.io.*;
            import java.util.*;

            public class Logon implements Serializable {

            ???????private Date date = new Date();
            ???????private String username;
            ???????private transient String password;


            ???????Logon(Stringname, String pwd) {
            ??????????????username = name;
            ??????????????password = pwd;
            ???????}


            ???????public String toString() {
            ??????????????String pwd = (password == null) ? "(n/a)" : password;
            ??????????????return "logon info: \n " + "username: " + username + "\n date: " + date + "\n password: " + pwd;
            ???????}


            ???????public static void
            main(String[] args) throws IOException, ClassNotFoundException {
            ??????????????Logon a = new Logon("Morgan", "morgan83");
            ??????????????System.out.println( "logon a = " + a);
            ??????????????ObjectOutputStream o = newObjectOutputStreamnewFileOutputStream"Logon.out"));
            ??????????????o.writeObject(a);
            ??????????????o.close();

            ??????????????int seconds = 5;
            ??????????????long t = System.currentTimeMillis()?+ seconds * 1000;
            ??????????????whileSystem.currentTimeMillis() < t) ;

            ??????????????ObjectInputStream in = new ObjectInputStreamnewFileInputStream"Logon.out"));
            ??????????????System.out.println( "Recovering object at " + new Date());
            ??????????????a = (Logon)in.readObject();
            ??????????????System.out.println("logon a = " + a);
            ???????}
            }

              類Logon是一個(gè)記錄登錄信息的類,包括用戶名和密碼。首先它實(shí)現(xiàn)了接口Serializable,這就標(biāo)志著它可以被序列化。之后再main方法里ObjectOutputStream o = newObjectOutputStreamnewFileOutputStream"Logon.out"));新建一個(gè)對(duì)象輸出流包裝一個(gè)文件流,表示對(duì)象序列化的目的地是文件Logon.out。然后用方法writeObject開始寫入。想要還原的時(shí)候也很簡(jiǎn)單ObjectInputStream in = newObjectInputStreamnewFileInputStream"Logon.out"));新建一個(gè)對(duì)象輸入流以文件流Logon.out為參數(shù),之后調(diào)用readObject方法就可以了。

              需要說(shuō)明一點(diǎn),對(duì)象序列化有一個(gè)神奇之處就是,它建立了一張對(duì)象網(wǎng),將當(dāng)前要序列化的對(duì)象中所持有的引用指向的對(duì)象都包含起來(lái)一起寫入到文件,更為奇妙的是,如果你一次序列化了好幾個(gè)對(duì)象,它們中相同的內(nèi)容將會(huì)被共享寫入。這的確是一個(gè)非常好的機(jī)制。它可以用來(lái)實(shí)現(xiàn)深層拷貝。

              關(guān)鍵字transient在這里表示當(dāng)前內(nèi)容將不被序列化,比如例子中的密碼,需要保密,所以沒有被寫入文

            久久93精品国产91久久综合| 99精品久久精品一区二区| 国产精品久久国产精麻豆99网站| 久久久久高潮综合影院| 久久久久久精品免费看SSS| 国产精品99久久免费观看| 国产精品久久久天天影视| 一本色综合久久| 99国产欧美精品久久久蜜芽| 亚洲午夜无码AV毛片久久| 久久超乳爆乳中文字幕| 无码乱码观看精品久久| 久久久久人妻一区二区三区vr| 亚洲综合久久综合激情久久| 久久精品成人欧美大片| 久久播电影网| 日日噜噜夜夜狠狠久久丁香五月 | 久久久久久毛片免费播放| 久久99精品免费一区二区| 国产精品国色综合久久| 亚洲∧v久久久无码精品| 伊人久久大香线蕉AV一区二区| 99久久国产综合精品成人影院| 欧美一区二区三区久久综| 精品久久久久久久国产潘金莲| 国产精品成人99久久久久| a高清免费毛片久久| 狠狠88综合久久久久综合网| 久久成人国产精品免费软件| 欧美亚洲国产精品久久高清| 久久国产精品无码网站| 国产精品一区二区久久精品无码| 久久精品成人免费看| 欧美久久精品一级c片片| 国产精品免费看久久久| 久久er99热精品一区二区| 韩国免费A级毛片久久| 久久精品国产亚洲AV麻豆网站| 色诱久久久久综合网ywww| 无码精品久久久久久人妻中字| 五月丁香综合激情六月久久|