<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    Jungleford's Home BlogJava分舵

    Java技術研究,兼探討歷史話題

    BlogJava 首頁 新隨筆 聯系 聚合 管理
      24 Posts :: 0 Stories :: 53 Comments :: 0 Trackbacks
    jungleford如是說

        PushbackInputStreamPushbackReaderJava I/O系統里兩個比較讓人迷惑的類,我以前對它(們)就不太了解,直到某一天看了以前水母Java版的牛人zms的評論和一些資料以后才有所獲益。這是幾個月以前的事情了,這幾天寫有關序列化的總結時才想到這也不失為一個好的話題。

    一個允許你反悔的hook

        Java I/O系統是一個典型的Decorator模式的實現,它以InputStream/OutputStream為基本核心,通過繼承關系,不斷為該核心添加新的功能,如文件流、緩沖、加解密等。對I/O系統設計模式感興趣的話,可以參考developerWorks上的一篇文章:從Java類庫看設計模式。Java I/O默認是不緩沖流的,所謂“緩沖”就是先把從流中得到的一塊字節序列暫存在一個被稱為buffer的內部字節數組里,然后你可以一下子取到這一整塊的字節數據,沒有緩沖的流只能一個字節一個字節讀,效率孰高孰低一目了然。有兩個特殊的輸入流實現了緩沖功能,一個是我們常用的BufferedInputStream,像讀文件我們常用

    BufferedInputStream in = new BufferedInputStream(new FileInputStream("datafile"));
    while ((b = in.
    read()) != -1)
    {
      ...
    }
    in.
    close();
     

        這是我們幾乎不用查什么JDK文檔就能信手拈來的代碼段,寫的時候也應該思考一下套一個BufferedInputStream的意義何在。另一個就是我們不怎么看到的PushbackInputStream(其對應的字符流模式為PushbackReader)。
        在通常狀態下,“流”意味著“一次性”,就是說你進行了一次操作后它的狀態就變了,譬如讀,無論是文件還是socket,你讀的過程中一個潛在的“讀指針”一樣的東東就在移動,你無法在讀以后再重新定位(當然RandomAccessFile是另一種情況),如果你以前奇怪為什么數據庫操作中ResultSet里get某個字段以后就不能再第二次get它了,這里或許是個解釋。但好在PushbackInputStream給了我們第二次讀的機會。我們先來區別一下“監聽”和“截獲”的概念,“監聽”就是把得到的消息copy一份,原始消息并不作任何改變地傳遞到目的地;而“截獲”則是先把消息“扣押”下來,不讓其自動轉給目標,而是先進行一些處理以后在轉發給目標(如果是網絡安全專業的背景知識,大概知道“監聽”是對“機密性”的攻擊,而“截獲”不僅是對“機密性”還是對“完整性”的攻擊)。有的朋友大概對hook這個名詞有些了解,它是一種Windows的一種消息處理機制,似乎就是一種消息截獲手段,但我對Windows編程幾乎一竅不通;此外,如果你熟悉Servlet的話,也能找到像Filter這樣的處理機制,在對每個HTTP請求/應答進行轉發之前,先在里頭耍一點花招,確定哪些予以轉發,哪些屏蔽掉,這也算是“截獲”吧。通過上面的介紹,我們不妨把PushbackInputStream看成是對輸入流的一種“截獲”手段,其中最重要的方法是unread:

    public void unread(int b) throws IOException
    public void
    unread(byte[] b) throws IOException
    public void
    unread(byte[] b, int off, int len) throws IOException

        我們可以想象一下,PushbackInputStream內置一個緩沖區(事實上,你可以從它的源代碼里找到這個protected的字節數組),當低層流進來時先流進這個buffer,在你把流“物歸原主”之前還有機會對它耍花招,然后再用unread方法“反悔”一下,把緩沖區里已經讀過的內容(一般是沒有被改動的,當然你也可以改動它,那就失去“歸趙”的意義了,因為已經不是“完璧”了)再插入到流的頭部,下次讀的時候是流剩余的部分再加上從緩沖區“歸還”的部分。上面三個unread方法分別代表從緩沖區“歸還”一個字節、一個字節數組以及一個字節數組中指定的部分。
        PushbackInputStream是對二進制流的處理,字符流下相對應的就是PushbackReader。

    有什么用?

        學過編譯的話就容易理解了,比如從左向右掃描字符流“for(int i=0;i<10;i++)”,掃描到“for”是不是就可以說是個關鍵字了呢?不行,說不定后面是“for1”,那就是個變量而不是關鍵字了,知道看到“(”才恍然大悟,哦,我可以安全地說“看到for關鍵字”了,但“(”還得歸還給輸入流,因為需要后面繼續掃描。在上下文相關語言里,就更需要這種補償機制。又如,在解析HTML文檔的時候,我需要根據它的“meta”標簽的“charset”屬性來決定使用哪種字符集進行解析,但HTML可不是“charset”而是“<html>”開頭的哦!所以需要通過PushbackInputStream緩沖前面一段內容,等取到字符集名稱后在把讀到的流全部歸還,再用指定的字符集進行解析。

    參考資料

    posted on 2005-04-02 22:03 jungleford 閱讀(700) 評論(0)  編輯  收藏 所屬分類: 咖啡屋 - Java 技術研究
    主站蜘蛛池模板: 免费a级毛片在线观看| 亚洲色偷偷综合亚洲av78| 久久精品熟女亚洲av麻豆| 国产一卡二卡3卡四卡免费| 国产一级婬片A视频免费观看| 久久免费美女视频| 亚洲AV永久无码精品一百度影院 | 亚洲国产福利精品一区二区| 日韩中文字幕免费视频| 久久免费国产精品一区二区| 亚洲欧洲日产国产综合网| 久久精品免费观看国产| 亚洲综合一区二区| 国产美女在线精品免费观看| 亚洲精品人成网在线播放影院| 久久久久国色AV免费看图片| 久久亚洲精品成人无码| 亚洲午夜国产片在线观看| baoyu116.永久免费视频| 亚洲高清无在码在线电影不卡| 69成人免费视频无码专区| 香港一级毛片免费看| 亚洲午夜久久久久久久久电影网| 成人久久免费网站| 亚洲国产日韩在线人成下载| 四虎www免费人成| 国产成人自产拍免费视频| 亚洲国产老鸭窝一区二区三区| 国产精品久久免费| 看成年女人免费午夜视频| 国产成人无码综合亚洲日韩 | 中文无码日韩欧免费视频| 337p日本欧洲亚洲大胆精品555588 | 在线观看亚洲专区| 亚洲综合图色40p| 在线观看免费av网站| 亚洲第一街区偷拍街拍| 亚洲日韩精品无码一区二区三区 | 日韩在线天堂免费观看| 精品国产福利尤物免费| 亚洲免费黄色网址|