posts - 2,  comments - 0,  trackbacks - 0

          ? 一直以來對IO這塊的東西認識都不是很清楚。每次涉及這塊的東西,一般都找點現成的代碼復制粘貼一下。這可不好,于是靜下心來好好弄一下。

          ?

          ?

          什么是IO?

          ??? 一提起IO給人的感覺就比較復雜(不過確實也挺復雜的),可能是學C的時候嚇怕了,呵呵。不過,理一下思路還是比較清晰的。在Java里,IO說白了就是對讀、寫的一種抽象。沒有什么其他的復雜的東西。至于讀什么、寫什么,那就看你想讀什么、想寫什么,由自己控制了。

          ?

          ?

          讀什么?寫什么?

          看看下面這個圖會清楚很多(只用看InputStream就行,OutputStream一樣):

          ?

          ?

          ?

          ???? 大家可以看一下直接繼承InputStream的幾個類ByteArrayInputStream、FileInputStream、StringBufferInputStream(PipedInputSteram和SequenceInputStream一般不用)。呵呵,看看這幾個類的構造函數就明了了。第一個是把byte數字作為IO源讀取byte數組里的東西,第二個是把文件作為IO源讀取文件里的東西,第三個是把String作為IO源讀取String里面的東西。這么看這幾個IO實在簡單。說白了就是從byte數組、文件、String按字節讀取罷了.....

          ??? 一句簡單的話說:IO體系第一級繼承的幾個類解決了從哪兒讀或者寫到哪兒的問題

          ?

          ?

          怎么讀?怎么寫?

          ??? 試想一下,現在要讀一個幾百兆的文件,怎么讀呢?是一下子把整個文件都讀到內存慢慢分析呢,還是每次讀只讀一個字節逐個分析呢?顯然兩個都不好,于是我們想到了緩沖。所以IO體系上有了BufferedInputStream。再想一下,現在你想寫一個“3.1415926”到文件里怎么寫?總不能自己把這個數的二進制形式寫出來,轉成byte數組寫到文件里吧。即便寫進去了讀的時候怎么讀啊?誰知道你寫進去的是數字而不是其他字符呢?

          ??? 于是針對怎么讀Java IO體系上出現了一個分支FilerInoutStream(FilterOutputStream)。繼承了這個類的幾個類各自對怎么讀、寫提供了不同的支持。Buffered提供了緩沖,LineNumber提供了對不同類型數據的讀寫。

          ??? 還是一句話:IO體系的第二級繼承解決了怎么讀、怎么寫

          ?

          ?

          以不變應萬變

          ??? 說IO不能不說他的Decorator(裝飾)模式。此模式在這里的應用確實很經典!從上面兩段的分析看來Java的IO就是分成兩部分從哪兒讀(寫)和怎么讀(寫)。想想看,一個數據源可能需要不同的讀寫方式、而不同的數據源都可能需要同一直讀寫方式。于是這里的組合方式是一種乘積。n個數據源×n中處理方式×(n-1)處理方式(有時候可能涉及多種處理方式的疊加)=n^3。想想看,要是一個一個寫還不寫死......

          ??? 從IO體系的根看,InputStream(OutputStream)提供了最根本的read(write)方法。各子類提供各自實現。而得益于Decorator,各子類還可以把自己的處理方式加到read(write)的前后,形成一種處理方式的疊加。

          ??? JDK這部分的代碼比較簡單。看一下就大概知道Decorator怎么實現的了。

          ?

          ?

          追根溯源

          ???? 我們見到的IO最大的應用一個應該是數據的持久化,FileinputStream(FileOutputStream)已經實現了。而另一個則是網絡傳輸。之前我就很想知道IO是怎么在網絡上實現傳輸的?還有上面說的幾個IO都不存在“阻塞”問題,那么IO的阻塞實在哪兒產生的呢?

          ???? 找了半天對于找到了下面一句:

          ???? class SocketInputStream extends FileInputStream

          ???? 再追下去就找到了一些native方法,這個就超出我能力之外了。不過可以猜想,底層的東西應該就是C的一些文件讀寫了。這個就不是Java的問題:)目前暫時這么認為,以后或許能發現一些新的東西。

          ?

          ?

          根深蒂固的痛——國際化

          ???? 編碼問題不僅是Java頭痛的問題,也是每一個用Java的人都頭痛的問題。IO也不例外。InputStream(OutputStream)體系都是針對字節(byte)進行讀寫的。這樣的問題是字節可能是沒有意義的,只有幾個字節聯合轉換才能得到有意義的東西。所以如果是字節還要再次進行編解碼才能得到我們想要的東西。

          ??? 為了避免這個麻煩,字符體系(Read、Write)產生了。他們可以對流進行編解碼,這樣可以直接得到用戶想要的東西。兩個體系大大體上都是對應的。再多的東西我也沒有深入了解了:)

          ??? 還有一個要提的是,什么時候用字符、什么時候用字節呢?TIJ里有交代:大部分時候用字符,字符不行的時候再考慮字節。呵呵,挺簡練的。

          ?

          ?

          日新月異

          ??? nio應該是老掉牙的東西了。不過對于我這個初始IO的人來說還有待進一步了解。目前知道兩點:上面的IO體系的底層都已經用nio重寫了,所以速度上應該差不多。這樣看來,一般情況下用上面的IO是沒問題的。再一個是,nio最大的優勢在于他的“非阻塞IO”,不過這個東東是用在網絡編程的。一般也用不上。

          ??? 再新的東西就是前兩天看到的一個blog,關于aio(異步IO)的大家有興趣可以自己看看。

          posted @ 2006-11-25 21:26 KeepRunning 閱讀(366) | 評論 (0)編輯 收藏
          這是我以前的Blog,現在也還在用。因為技術方面的東西沒人關注,呵呵,所以還是把技術的東西放到技術的地方,或許更能找到共同的語音:)

          順便貼一篇,歡迎討論~

          重拾聚集(Collection)


          大家先來看段代碼吧:

          List list = new ArrayList();
          list.add("exception");
          for (Iterator iter = list.iterator(); iter.hasNext();) {
          ???? String element = (String) iter.next();
          ???? list.remove(element);
          }

          這段代碼運行時會拋出異常,呵呵,不知道大家發現問題沒?

          ?

          這段代碼會拋出:java.util.ConcurrentModificationException。也就是所謂的“Fail Fast”。用了很久Java了,才發現這么一個異常,著實郁悶了一把......啥都不說了,拿起書來,重新來過。

          ?

          為什么要Iterator?

          下面是一個Collection的總體圖:

          ?

          ?

          ??? 上面代碼涉及了一個經典的涉及模式-Iterator模式。既然涉及了這個模式,就要問問為什么這里要用這個模式。查了一下書,有這么幾句描述Iterator的:迭代邏輯沒有改變,但是需要將一種聚集變換成另一種聚集。因為不同的聚集遍歷接口不同,所以需要修改客戶端代碼。這幾句話沒錯,而且我們用Iterator都有如文章開頭示例的標準方式,然而仔細想來卻還有點問題。

          ??? 假設Iterator是為了實現遍歷方便。可是,我們幾個常用的聚集(如:ArrayList,LinkedList,Set等)都已經間接實現了Collection接口。而大家應該注意到Collection接口中有個size()方法。這樣的結果是,對所有實現了Collection的聚集而言,我們都可以通過for (int i = 0; i < list.size(); i++)這樣的形式實現遍歷。而且,JDK1.5還可以通過foreach的形式大大簡化代碼量。所以,這樣想來Iterator為了實現遍歷的方便而引入,顯然不成立。

          ??? 接著找找。我們可以注意到,Set和List兩個大類中一個很大的區別是:List提供get方法,而Set沒有提供get方法。這樣的結果是Set類只能往集合中放,卻不能從集合中取(從一般的常識來說,這樣做還是合理的)。呵呵,所以這里我只能猜想Iterator是不是是為了訪問Set中元素而設計的了。

          ??? 僅僅猜想,不知道大家有沒有什么更好的想法?

          ?

          討論:

          ???? 跟朋友討論了一下,for(int i = 0; i < list.size(); i++)對應遍歷LinkedList來說是致命的。對ArrayList是O(n),而LinkedList則是O(n^2),這樣的效率是不能讓人接受的。

          ????如上所說,那么foreach的引入應該是在編譯層次對兩種不同數據結構進行了不同處理。而且成為了Iterator的替代。

          ??? 不過這里又引出了另一個問題——

          ???????????Iterator模式如何用在其他地方?作為一種設計模式Iterator應該有更廣的使用價值吧~

          ?

          ?

          Iterator的缺點

          1. ??? 聚集中的元素有些是有順序的,而有些是沒有順序可言的。使用過度Iterator會產生一種元素順序的誤解。
          2. ??? Iterator給出的元素沒有類型。這點很致命啊。而且也是JDK1.5一大優勢。
          3. ??? Iterator使得某些同步的類在使用了Iterator后,成為不同步(不能說不同步,只是Iterator無法并發)。如Vector

          ??? 這里沒有貶低Iterator的意思,只是實在看不出他有啥好處......

          ?

          集合

          能力有限,感覺了解還是太少,也沒太多好說的,只是有些區別應該注意一下。

          1. 繼承List的幾個類中,只有Vector是同步的。當然也包括Vector的子類Stack。
          2. 如果需要對不同步的List,Set等可以考慮使用Collections類中的方法。

          posted @ 2006-11-19 21:32 KeepRunning 閱讀(306) | 評論 (0)編輯 收藏
          <2006年11月>
          2930311234
          567891011
          12131415161718
          19202122232425
          262728293012
          3456789

          常用鏈接

          留言簿(1)

          隨筆分類

          隨筆檔案

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 丹阳市| 丰县| 潢川县| 隆昌县| 乌拉特中旗| 淳化县| 英吉沙县| 侯马市| 江西省| 吴桥县| 舞钢市| 深圳市| 泰和县| 睢宁县| 连城县| 太仓市| 丹凤县| 将乐县| 育儿| 绵竹市| 扎兰屯市| 静海县| 兴山县| 二手房| 金华市| 柳州市| 申扎县| 平邑县| 苏尼特右旗| 东山县| 德庆县| 安宁市| 寻甸| 柏乡县| 陇川县| 清涧县| 韶山市| 广东省| 红桥区| 万源市| 塔河县|