Java NIO Buffer(四)

 

原文連接:http://tutorials.jenkov.com/java-nio/buffers.html,若有侵權,立刪。html

Java NIO Buffer

  • buffer的基本使用
  • buffer的capacity、position、limit屬性
  • buffer類型
  • 分配緩存區
  • 向buffer中寫入數據
  • flip()方法
  • 從buffer中讀取數據
  • rewind()方法
  • clear()和compact()方法
  • mark()和reset()方法
  • equal()和compareTo()方法

  Java buffer 和 channel 是相輔相成的,正如前文所言,經過channel寫入數據到buffer中,經過channel從buffer中讀取數據。java

  buffer是一個高校的內存塊,供你寫入數據用。這些內存塊在buffer中被包裝起來了,而且提供了方法讓你輕鬆使用內存塊。緩存

   Basic Buffer Usage

  用buffer進行讀取或寫入數據,一般有以下四個步驟:app

  1. 向buffer中寫入數據
  2. 調用buffer的flip()方法
  3. 從buffer中讀取出數據
  4. 調用buffer的clear()或者compact()方法

  當你向buffer中寫入數據,buffer會保存你向其中寫入了多少個byte。一旦你從buffer中讀取數據,你須要將buffer從寫模式轉化爲讀模式,經過flip()方法。dom

  一旦你讀取到全部的data後,你須要清空緩存區,讓buffer爲下一次寫入作準備。你能夠經過兩種方法,clear()和compact()。clear()方法會清空全部的緩存,compact()方法僅僅清空你已經讀過的數據。沒有讀過的數據會被轉移到buffer的開始處,會在沒有讀過的數據後寫入新數據。this

  如下是一個簡單的例子spa

  

 1 RandomAccessFile aFile = new RandomAccessFile("data/nio-data.txt", "rw");
 2 FileChannel inChannel = aFile.getChannel();
 3 
 4 //create buffer with capacity of 48 bytes
 5 ByteBuffer buf = ByteBuffer.allocate(48);
 6 
 7 int bytesRead = inChannel.read(buf); //read into buffer.
 8 while (bytesRead != -1) {
 9 
10   buf.flip();  //make buffer ready for read
11 
12   while(buf.hasRemaining()){
13       System.out.print((char) buf.get()); // read 1 byte at a time
14   }
15 
16   buf.clear(); //make buffer ready for writing
17   bytesRead = inChannel.read(buf);
18 }
19 aFile.close();

 Buffer Capacity、Position、Limit

  position和limit的含義會隨着buffer的模式轉換而不一樣,capacity不管哪種模式,含義都是相同的。放兩張圖上來code

                    

  Capacity,在建立一個緩存區時,緩存區的大小是固定的。你只能向緩存區中寫入capacity的數據量,一旦緩存區滿了,你須要在下一次寫入新的數據時,經過clear()方法清空緩存區。htm

  position,當你想緩存區寫入數據時,你須要清楚你寫到了哪一個位置。position初始化爲0,寫入多少byte,position就會移動多少。position的最大值是capacity-1。blog

  當你從緩存區讀取數據時,要從給定的position處開始讀。當你使用flip()方法,將buffer的寫模式轉換爲讀模式。position會被初始化爲0,當你從buffer中讀取出數據時,position會提早移到下一個要讀的位置。

  limit,在寫模式中,limit就表明着你能夠向buffer中寫入多少數據,在寫模式中limit等於capacity。

  當轉換buffer爲讀模式時,limit意味着你能夠讀取多少數據。所以,當buffer轉換爲讀模式時,limit會被賦值爲寫模式中的position。另外一種是,你寫進去多少數據就讀多少數據(limit被賦值爲寫入buffer中的字節數)

 Buffer Types

  Java NIO 有如下幾種buffer類型

  1. ByteBuffer
  2. CharBuffer
  3. ShortBuffer
  4. IntBuffer
  5. LongBuffer
  6. FloatBuffer
  7. DoubleBuffer
  8. MappedByteBuffer

  正如你所看見的那樣,不一樣的buffer類型表明了不一樣的基本數據類型。

  MappedByteBuffer是一種特殊的buffer類型,以後再討論它。

 Allocating a Buffer

  在得到buffer以前,你必須進行分配。每個Buffer類都有allocate()方法來進行分配,這裏有一個例子,展現如何分配內存

ByteBuffer buf = ByteBuffer.allocate(48);

 

 Writing Data to a Buffer

  你能夠經過兩種方法向buffer寫入數據

  1. 從channel向buffer寫入數據
  2. 經過buffer本身的put()方法,向buffer寫入數據

  例子:

1 int bytesRead = inChannel.read(buf); //read into buffer.

 

1 buf.put(127);    

 

這裏還有不少put()方法的其餘版本,容許你經過不一樣的方法向buffer中寫入數據。

 flip()

  flip()方法將buffer從寫模式轉化爲讀模式。做用看代碼:

1     public final Buffer flip() {
2         limit = position;
3         position = 0;
4         mark = -1;
5         return this;
6     }

 

 Reading Data From a Buffer

  這裏有兩種從buffer中讀取數據的方法

  1. 經過channel讀取數據
  2. 調用buffer本身的get()方法,讀取數據

  例子:

1 //read from buffer into channel.
2 int bytesWritten = inChannel.write(buf);
1 byte aByte = buf.get();  

 

  一樣,也有不少版本的get()方法供你使用。

 rewind() 

  先貼上代碼:

1     public final Buffer rewind() {
2         position = 0;
3         mark = -1;
4         return this;
5     }

  將position賦值爲0,其他的不作變化。能夠從頭開始讀取數據。

 clear()和compact()

  一旦你從buffer中讀取完數據,你必須讓buffer準備好下一次寫入。你能夠調用clear()方法和compact()方法。

  clear方法,會將position設置爲0,仍是上源碼吧

1     public final Buffer clear() {
2         position = 0;
3         limit = capacity;
4         mark = -1;
5         return this;
6     }

 

  源碼的註釋說明:實際上clear()方法並不會將數據從緩存區中擦除,只是名字搞的鬼,由於大多數狀況他確實會被用類清除數據

  compact()方法,會將你沒有讀完的數據複製到buffer的開始處,而後將position設置爲未讀數據的下一個位置。

 mark()和reset()

  在buffer中你能夠調用mark()方法標記一個給定的position位置,以後你能夠經過調用reset()方法,從新設置position到剛剛mark()的位置。能夠本身試驗下

1 buffer.mark();
2 
3 //call buffer.get() a couple of times, e.g. during parsing.
4 
5 buffer.reset();  //set position back to mark.   

 

 equals()和compareTo()

  兩個比較buffer的方法

  equals(),當知足如下條件時,爲true

  1. 他們是相同的類型的buffer
  2. 他們有相同的剩餘字節量
  3. 全部剩餘的數據都相等

  正如你所看到的,equals()只能判斷buffer的一部分數據。直接上源碼

 1     public boolean equals(Object ob) {
 2         if (this == ob)
 3             return true;
 4         if (!(ob instanceof ByteBuffer))
 5             return false;
 6         ByteBuffer that = (ByteBuffer)ob;
 7         if (this.remaining() != that.remaining())
 8             return false;
 9         int p = this.position();
10         for (int i = this.limit() - 1, j = that.limit() - 1; i >= p; i--, j--)
11             if (!equals(this.get(i), that.get(j)))
12                 return false;
13         return true;
14     }

 

  compareTo(),直接上源碼了

1     public int compareTo(ByteBuffer that) {
2         int n = this.position() + Math.min(this.remaining(), that.remaining());
3         for (int i = this.position(), j = that.position(); i < n; i++, j++) {
4             int cmp = compare(this.get(i), that.get(j));
5             if (cmp != 0)
6                 return cmp;
7         }
8         return this.remaining() - that.remaining();
9     }
相關文章
相關標籤/搜索