一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

java.nio.*

 鳳舞天煌 2007-11-12

             JDK 1.4的java.nio.*包中引入了新的JavaI/O類庫,其目的在于提高速度。(實(shí)際上,舊的I/O包已經(jīng)使用nio重新實(shí)現(xiàn)過,以便充分利用這種速度,即使我們不顯式地用nio編寫代碼,也能從中受益!

             nio速度的提高來自于所使用的結(jié)構(gòu)更接近于操作系統(tǒng)執(zhí)行I/O的方式(Java執(zhí)行I/O接近于操作系統(tǒng)執(zhí)行I/O,所以速度得到了提高):通道和緩沖器。我們可以把它想象成一個煤礦,通道是一個包含煤層(數(shù)據(jù))的礦藏,而緩沖器則是派送到礦藏的卡車。卡車載滿煤炭而歸,我們再從卡車上獲得煤炭。也就是說,我們要讀書到數(shù)據(jù),并沒有直接和通道交互;只是和緩沖器交互,并把緩沖器派送到通道。通道要么從緩沖器獲得數(shù)據(jù),要么向緩沖器發(fā)送數(shù)據(jù)!

             唯一直接與通道交互的緩沖器是ByteBuffer,它是java.nio里面的類:通過告知分配多少存儲空間來創(chuàng)建一個ByteBuffer對象,并且還有一個方法選擇集,用以原始的字節(jié)形式或基本數(shù)據(jù)類型輸出和讀取數(shù)據(jù)。但是沒辦法輸出或讀取對象,即使是字符串對象也不行;

          ByteBuffer是一個抽象類,不能直接創(chuàng)建實(shí)例,可以調(diào)用該類的static方法allocate(int capacity)來創(chuàng)建它的一個新緩沖區(qū),該緩沖區(qū)的位置將為零,其界限將為其容量,其標(biāo)記是不確定的。它將具有一個底層實(shí)現(xiàn)數(shù)組,且其 數(shù)組偏移量將為零。

           關(guān)于通道,這里介紹一個文件通道FileChannel,它也是一個抽象類,也不能直接創(chuàng)建實(shí)例。舊的I/O類庫中有本個類被修改過了,可以用它們的getChannel()來返回一個FileChannel對象(更確切的說應(yīng)該是返回FileChannel的一個匿名子類的對象)。這三個能返回FileChannel的類是:FileInputStream,FileOutputStream,RandomAccessFile 。值得注意的是它們都是字節(jié)流的,Reader與Writer這兩個處理字符流的類不能用于通道,不過java,nio.channels.Channels類提供了實(shí)用方法,用以在通道中產(chǎn)生Reader與Writer(想了解更多請查API文檔,這里不介紹)!
===========================================================================================
緩沖區(qū)是特定基本類型元素的線性有限序列。除內(nèi)容外,緩沖區(qū)的基本屬性還包括容量、限制和位置:

緩沖區(qū)的容量 是它所包含的元素的數(shù)量。緩沖區(qū)的容量不能為負(fù)并且不能更改。

緩沖區(qū)的限制 是第一個不應(yīng)該讀取或?qū)懭氲脑氐乃饕>彌_區(qū)的限制不能為負(fù),并且不能大于其容量。

緩沖區(qū)的位置 是下一個要讀取或?qū)懭氲脑氐乃饕?。緩沖區(qū)的位置不能為負(fù),并且不能大于其限制。

  因此,我們從緩沖區(qū)讀書數(shù)據(jù),其實(shí)是從此緩沖區(qū)的“位置”處一直讀到“限制”處!


============================================================================================
           關(guān)于緩沖器ByteBuffer,最令人捉摸不清的可能是它的三個方法:flip();clear();remind()
這三個方法一般是和FileChannel的read(ByteBuffer bf)與write(ByteBuffer bf)混合在一起使用的!
   
               FileChannel的read(ByteBuffer bf):將字節(jié)序列從FileChannel讀入給定的緩沖區(qū)ByteBuffer bf 中!讀完以后,bf的當(dāng)前位置就是從FileChannel中讀取的字節(jié)個數(shù)!
              同理,我們應(yīng)該可以很容易想象出write(ByteBuffer bf)它就是用來將字節(jié)序列從給定的緩沖區(qū)ByteBuffer bf寫入通道FileChannel。
    
              ByteBuffer的flip():反轉(zhuǎn)此緩沖區(qū),將限制設(shè)置為當(dāng)前位置,然后將位置設(shè)置為 0 !
     
               ByteBuffer的clear();“清除”此緩沖區(qū),將位置設(shè)置為 0,將限制設(shè)置為容量!
此方法不能實(shí)際清除緩沖區(qū)中的數(shù)據(jù),但從名稱來看它似乎能夠這樣做,這樣命名是因?yàn)樗鄶?shù)情況下確實(shí)是在清除數(shù)據(jù)時使用。因?yàn)檎{(diào)用該方法后,我們一般都會調(diào)用FileChannel.read(buff)或者buff.put()來把新的數(shù)據(jù)放到buff中,此時原來的內(nèi)容就會被新的內(nèi)容所覆蓋!也不是全部覆蓋,而是覆蓋掉新數(shù)據(jù)所包含的字節(jié)數(shù)!所以看起來好象就是原來的內(nèi)容被刪除一樣!

             remind(),重繞此緩沖區(qū),將位置設(shè)置為 0 并丟棄標(biāo)記。此方法與flip()的區(qū)別是:remind()不會把限制設(shè)置為當(dāng)前位置,而是保持限制不變!與clear()的區(qū)別是:remind()不會把限制設(shè)置為容量,而是保持限制不變!

==========================================================================================
講了這么多,你們不暈,我都暈了,那么現(xiàn)在來點(diǎn)實(shí)際的代碼,以幫助理解!

//例一:
import java.nio.channels.*;
import java.io.*;

public class GetChannel {
           private static final int BSIZE = 1024;
           public static void main(String[] args) throws Exception {
             // Write a file:
             FileChannel fc =
               new FileOutputStream("data.txt").getChannel();
             fc.write(ByteBuffer.wrap("Some text ".getBytes()));
             fc.close();
             // Add to the end of the file:
             fc =
               new RandomAccessFile("data.txt", "rw").getChannel();
             fc.position(fc.size()); //
將通道位置移動到最后,以便我們在通道后面繼續(xù)寫入新數(shù)據(jù)
             fc.write(ByteBuffer.wrap("Some more".getBytes()));
             fc.close();
             // Read the file:
             fc = new FileInputStream("data.txt").getChannel();
             ByteBuffer buff = ByteBuffer.allocate(BSIZE);
             fc.read(buff);
//把通道中的字節(jié)序列讀入buff中

             //進(jìn)行此操作后,buff的位置移動了從FileChannel中讀取的字節(jié)個數(shù)!

             buff.flip();           //為下面的buff.get()做準(zhǔn)備,將buff的限制設(shè)置為當(dāng)前位置,然后將位置設(shè)置為 0
            //因?yàn)槲覀儚腷uff讀取,是從此buff的位置處一直讀到限制處!
             while(buff.hasRemaining())
               System.out.print((char)buff.get());
           }
} /* Output:
Some text Some more
*///:~
=========================================================================================
//例二:

// Copying a file using channels and buffers
// {Args: ChannelCopy.java test.txt}
import java.nio.*;
import java.nio.channels.*;
import java.io.*;

public class ChannelCopy {
           private static final int BSIZE = 1024;
           public static void main(String[] args) throws Exception {
             if(args.length != 2) {
               System.out.println("arguments: sourcefile destfile");
               System.exit(1);
             }
             FileChannel
               in = new FileInputStream(args[0]).getChannel(),
               out = new FileOutputStream(args[1]).getChannel();
             ByteBuffer buffer = ByteBuffer.allocate(BSIZE);
             while(in.read(buffer) != -1) {           //buffer 用來向FileChannel讀取數(shù)據(jù)

         //其實(shí)此循環(huán)只會執(zhí)行一次,因?yàn)閳?zhí)行一次就會把FileChannel中的全部數(shù)據(jù)都讀到buffer中
               buffer.flip(); // 為通道寫入做準(zhǔn)備
               out.write(buffer); //buffer 用來向FileChannel寫入數(shù)據(jù)
               buffer.clear();           // 為通道再次讀取做準(zhǔn)備
             }
           }
} ///:~

 

============================啟示================================

當(dāng)對flip(),clear(),remind()不是很理解而正在考慮某個地方是否需要這三個方法時,我們還可以調(diào)用limit(),position(),remainning()等方法來進(jìn)行調(diào)試。

public final int limit()
返回此緩沖區(qū)的限制。
public final int position()
返回此緩沖區(qū)的當(dāng)前位置。
public final int remaining()
返回當(dāng)前位置與限制之間的元素數(shù)。

======================================================================

上面的兩個例子,是因?yàn)橛蠪ileChannel的read()或者write(),以至把ByteBuffer中的位置移動了相應(yīng)的字節(jié)數(shù)。然后調(diào)用flip時,就把限制設(shè)置為當(dāng)前位置。此時的position就不為0了。下面的例子中,沒有FileChannel的參與,當(dāng)前位置也就沒有了變化,此時,若再調(diào)用flip,由于當(dāng)前位置是0,設(shè)置為限制后,限制也變成0,若我們要從限制為0的ByteBuffer中讀取數(shù)據(jù),此時就什么也沒讀到,可能還會拋出異常。那么解決的方法就是調(diào)用rewind(),此方法,只是把位置設(shè)置為0,而不會改變其限制,這時,限制就仍為容量。因?yàn)橛?font color=#0000ff>ByteBuffer的static allocated()時,新緩沖區(qū)的位置將為零,其限制將為其容量!

另外,調(diào)用ByteBuffer的get()與put()時,會把position移動一個字節(jié)!而調(diào)用這兩個方法的帶參數(shù)版本則不會改變position的值,這里還要區(qū)別一下兩種情況的put方法:

   情況一:

    ByteBuffer bb = ByteBuffer.allocate(1024);
    CharBuffer cb = bb.asCharBuffer(); //創(chuàng)建ByteBuffer的Char視圖

    cb.put("Hwdy!"); ////字符串中的每個字符占1個字節(jié)!共占5個字節(jié)!所以此句會使position移動5個字節(jié)!

 

===================================================================

情況二:

ByteBuffer bb = ByteBuffer.allocate(BSIZE);
    bb.asCharBuffer().put("Howdy"); //用這種形式來創(chuàng)建視圖不會移動bb的position

     print(bb.position()); //所以此處的postion值為0

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    字幕日本欧美一区二区| 一区二区三区四区亚洲专区| 亚洲男人的天堂久久a| 中日韩美一级特黄大片| 中文字日产幕码三区国产| 欧美一区二区三区高潮菊竹| 日本高清视频在线观看不卡| 一本久道久久综合中文字幕| 在线一区二区免费的视频| 亚洲成人精品免费在线观看| 中文字幕亚洲精品在线播放| 九九热精品视频免费在线播放| 国产欧美韩日一区二区三区| 国产欧美日产中文一区| 日本人妻丰满熟妇久久| 国产亚洲成av人在线观看| 欧美极品欧美精品欧美| 福利在线午夜绝顶三级| 小草少妇视频免费看视频| 美国黑人一级黄色大片| 激情少妇一区二区三区| 国产麻豆一线二线三线| 又大又长又粗又黄国产| 日本中文字幕在线精品| 日韩免费午夜福利视频| 精品一区二区三区乱码中文| 一级片二级片欧美日韩| 日韩欧美中文字幕av| 亚洲三级视频在线观看免费| 六月丁香六月综合缴情| 日韩精品小视频在线观看| 国产精品一区二区香蕉视频| 深夜福利欲求不满的人妻| 亚洲一区二区三区av高清| 亚洲国产性生活高潮免费视频| 日本午夜一本久久久综合| 日韩女优视频国产一区| 亚洲黑人精品一区二区欧美| 高清一区二区三区四区五区| 欧美乱码精品一区二区三| 国产伦精品一区二区三区精品视频|