java.nio.Buffer系の使い方を理解したい
java.nio.Buffer系がよく分からなかった。でも、色々調べたりしたら分かってきた。
今後のためのメモ。
容量
文字通りそのバッファの容量。どの位、確保するか。
CharBufferを容量10文字で使おうと思ったら、まず以下のように宣言する必要がある。
CharBuffer cb = CharBuffer.allocate(10);
リミット
これがよく分からなくて、ハマった。
リミットは読み込み、書き込みできる要素の限界のこと。
例えば、以下のように容量を10文字確保してからリミットを5に設定すると5文字分しか使えない。
よって、6文字分をバッファに格納しようとするとエラーになる。容量は10文字分あるんだけどね。
CharBuffer cb = CharBuffer.allocate(10); cb.limit(5); cb.put("ABCDEF"); //error
また、容量とリミットの関係は以下の通り
容量 >= リミット
ポジション(位置)
バッファがどの位置にいるかを表す。
一文字読めば、一文字進むし。
一文字書けば、一文字進む。
CharBuffer cb = CharBuffer.allocate(10); cb.position(); // 0 初期位置 cb.put("A"); // 1文字呼んで、1文字進む cb.position(); // 1
ボジション(位置)はリミットを超えることができないので、
リミット >= ポジション(位置)
リマイニング
現在のポジション(位置)からリミットまでの要素数。
CharBuffer cb = CharBuffer.allocate(10); cb.remaining(); // 10 cb.put("A"); // 1文字呼んで、1文字進む cb.remaining(); // 9
確認
java.nio.Buffer系の使い方が分からないので簡単なサンプルを作ってみた。 - ぐらめぬ・ぜぷつぇんのはてダ(2007 to 2011)を参考に、というかパクらせて頂いて、
確認のプログラムを書いてみた。
1 import java.nio.CharBuffer; 2 3 public class BufferUtil { 4 public BufferUtil() { 5 } 6 7 public static void dump(CharBuffer b) { 8 System.out.print("---> capacity[" +b.capacity() +"],"); 9 System.out.print("position[" +b.position() +"],"); 10 System.out.print("limit[" +b.limit() +"],"); 11 System.out.print("remaining[" +b.remaining() +"],"); 12 System.out.println("length[" +b.length() +"]"); 13 } 14 15 public static void dump(String str, CharBuffer b) { 16 System.out.println(str); 17 System.out.print("--- >capacity[" +b.capacity() +"],"); 18 System.out.print("position[" +b.position() +"],"); 19 System.out.print("limit[" +b.limit() +"],"); 20 System.out.print("remaining[" +b.remaining() +"],"); 21 System.out.println("length[" +b.length() +"]"); 22 } 23 24 }
1 import java.nio.CharBuffer; 2 import java.nio.BufferOverflowException; 3 4 public class Hoge { 5 6 public static void dumpCharBuffer(CharBuffer b) { 7 char c = '\0'; 8 9 while (b.hasRemaining()) { 10 c = b.get(); 11 if (c != 0) System.out.print("[" +c +"]: "); 12 else System.out.print("[ ]: "); 13 BufferUtil.dump(b); 14 } 15 } 16 17 public static void main(String[] args) { 18 CharBuffer cb = CharBuffer.allocate(64); 19 BufferUtil.dump("allocate(64)",cb); 20 cb.limit(16); 21 BufferUtil.dump("limit(16)",cb); 22 cb.put("abcde".toCharArray()); 23 BufferUtil.dump("put(\"abcde\")",cb); 24 cb.rewind(); 25 BufferUtil.dump("rewind()",cb); 26 System.out.println("read buffer"); 27 dumpCharBuffer(cb); 28 System.out.println("----------------"); 29 try { 30 System.out.println("put(\"ABC\")"); 31 cb.put("ABC".toCharArray()); 32 BufferUtil.dump(cb); 33 } catch (BufferOverflowException e) { 34 System.out.println("Buffer Overflow!"); 35 } 36 System.out.println("---------------"); 37 cb.position(5); 38 cb.mark(); 39 BufferUtil.dump("position(5),mark()",cb); 40 cb.put("DEF".toCharArray()); 41 BufferUtil.dump("put(\"DEF\")",cb); 42 cb.reset(); 43 BufferUtil.dump("reset()",cb); 44 dumpCharBuffer(cb); 45 cb.clear(); 46 BufferUtil.dump("clear()",cb); 47 cb.put("GHI".toCharArray()); 48 cb.flip(); 49 BufferUtil.dump("put(\"GHI\"),flip()",cb); 50 System.out.println("read buffer"); 51 dumpCharBuffer(cb); 52 } 53 }
実行結果
~/Desktop 10763 $ java Hoge allocate(64) --- >capacity[64],position[0],limit[64],remaining[64],length[64] limit(16) --- >capacity[64],position[0],limit[16],remaining[16],length[16] put("abcde") --- >capacity[64],position[5],limit[16],remaining[11],length[11] rewind() --- >capacity[64],position[0],limit[16],remaining[16],length[16] read buffer [a]: ---> capacity[64],position[1],limit[16],remaining[15],length[15] [b]: ---> capacity[64],position[2],limit[16],remaining[14],length[14] [c]: ---> capacity[64],position[3],limit[16],remaining[13],length[13] [d]: ---> capacity[64],position[4],limit[16],remaining[12],length[12] [e]: ---> capacity[64],position[5],limit[16],remaining[11],length[11] [ ]: ---> capacity[64],position[6],limit[16],remaining[10],length[10] [ ]: ---> capacity[64],position[7],limit[16],remaining[9],length[9] [ ]: ---> capacity[64],position[8],limit[16],remaining[8],length[8] [ ]: ---> capacity[64],position[9],limit[16],remaining[7],length[7] [ ]: ---> capacity[64],position[10],limit[16],remaining[6],length[6] [ ]: ---> capacity[64],position[11],limit[16],remaining[5],length[5] [ ]: ---> capacity[64],position[12],limit[16],remaining[4],length[4] [ ]: ---> capacity[64],position[13],limit[16],remaining[3],length[3] [ ]: ---> capacity[64],position[14],limit[16],remaining[2],length[2] [ ]: ---> capacity[64],position[15],limit[16],remaining[1],length[1] [ ]: ---> capacity[64],position[16],limit[16],remaining[0],length[0] ---------------- put("ABC") Buffer Overflow! --------------- position(5),mark() --- >capacity[64],position[5],limit[16],remaining[11],length[11] put("DEF") --- >capacity[64],position[8],limit[16],remaining[8],length[8] reset() --- >capacity[64],position[5],limit[16],remaining[11],length[11] [D]: ---> capacity[64],position[6],limit[16],remaining[10],length[10] [E]: ---> capacity[64],position[7],limit[16],remaining[9],length[9] [F]: ---> capacity[64],position[8],limit[16],remaining[8],length[8] [ ]: ---> capacity[64],position[9],limit[16],remaining[7],length[7] [ ]: ---> capacity[64],position[10],limit[16],remaining[6],length[6] [ ]: ---> capacity[64],position[11],limit[16],remaining[5],length[5] [ ]: ---> capacity[64],position[12],limit[16],remaining[4],length[4] [ ]: ---> capacity[64],position[13],limit[16],remaining[3],length[3] [ ]: ---> capacity[64],position[14],limit[16],remaining[2],length[2] [ ]: ---> capacity[64],position[15],limit[16],remaining[1],length[1] [ ]: ---> capacity[64],position[16],limit[16],remaining[0],length[0] clear() --- >capacity[64],position[0],limit[64],remaining[64],length[64] put("GHI"),flip() --- >capacity[64],position[0],limit[3],remaining[3],length[3] read buffer [G]: ---> capacity[64],position[1],limit[3],remaining[2],length[2] [H]: ---> capacity[64],position[2],limit[3],remaining[1],length[1] [I]: ---> capacity[64],position[3],limit[3],remaining[0],length[0]
簡単な解説
clear() flip() rewind()について
Oracle Technology Network for Java Developers | Oracle Technology Network | Oracle
clear() は、新しい一連のチャネル読み込み操作または相対「put」操作のためにバッファを準備します。リミットを容量の値に設定し、位置を 0 に設定します。 flip() は、新規チャネル書き込みシーケンス (相対「get」) のためにバッファを準備します。リミットの値を現在位置の値に合わせたあと、位置の値を 0 にします。 rewind() は、すでにバッファ格納されているデータを再度読み込めるように、バッファを準備します。リミットの値はそのままで、位置の値を 0 にします。
ポジション(位置)を0にするのは共通で、リミットの値が異なります。
flip()の使いどころは、
java.nio.Buffer系の使い方が分からないので簡単なサンプルを作ってみた。 - ぐらめぬ・ぜぷつぇんのはてダ(2007 to 2011)
flip()というのは、Bufferに書き込まれた分だけちょうど取得したい時に呼んでおく、という使い方が出来るようです。
ということですね。
37 cb.position(5); 38 cb.mark();
ポジション(位置)5に移動して、そこの位置をマークしておく。
そうして、以下のようにリセットするとポジションがマークしておいた位置に戻る。
42 cb.reset();
謝辞
java.nio.Buffer系の使い方を少しは理解できた。
それは、id:msakamoto-sfさんの
java.nio.Buffer系の使い方が分からないので簡単なサンプルを作ってみた。 - ぐらめぬ・ぜぷつぇんのはてダ(2007 to 2011)を読んだからです。
この記事がなかったら、理解できていなかっただろうと思います。
本当に、ありがとうございました。