JAVAでのバッファの使用法

怪我咯
リリース: 2017-06-25 10:14:49
オリジナル
4895 人が閲覧しました

注: Concurrent Programming Network、Java nio シリーズ チュートリアルから転載

1. バッファ

Java NIO のバッファは、NIO チャネルと対話するために使用されます。ご存知のとおり、データはチャネルからバッファに読み取られ、バッファからチャネルに書き込まれます。

バッファは本質的に、データを書き込んだりそこからデータを読み取ったりできるメモリのブロックです。このメモリは NIO バッファ オブジェクトとしてパッケージ化されており、このメモリに簡単にアクセスするための一連のメソッドを提供します。

1. Buffer の基本的な使用方法

Buffer を使用してデータを読み書きするには、通常次の 4 つの手順に従います:

  1. Buffer にデータを書き込む

  2. flip() メソッドを呼び出すflip()方法

  3. 从Buffer中读取数据:如直接读取或读取到Channel中

  4. 调用clear()方法或者compact()

バッファからのデータの読み取り: 直接読み取りまたはチャネルへの読み取りなど

clear() メソッドまたは compact() メソッドを呼び出します

バッファにデータを書き込むとき、バッファには書き込まれたデータの量が記録されます。データを読み取りたい場合は、flip() メソッドを通じてバッファを書き込みモードから読み取りモードに切り替える必要があります。読み取りモードでは、以前にバッファに書き込まれたすべてのデータを読み取ることができます。

すべてのデータが読み取られたら、再度書き込むことができるようにバッファをクリアする必要があります。バッファをクリアするには 2 つの方法があります。clear() メソッドまたは Compact() メソッドを呼び出すことです。 clear() メソッドはバッファ全体をクリアします。 Compact() メソッドは、読み取られたデータのみをクリアします。未読のデータはバッファの先頭に移動され、新しく書き込まれたデータはバッファ内の未読のデータの後に配置されます。

  • 2. バッファの容量、位置、および制限

    バッファは本質的に、データを書き込んだり、データを読み取ったりできるメモリの一部です。このメモリは NIO バッファ オブジェクトとしてパッケージ化されており、このメモリに簡単にアクセスするための一連のメソッドを提供します。
  • バッファがどのように機能するかを理解するには、その 3 つのプロパティを理解する必要があります:

  • 容量

位置

制限

位置と制限の意味は、バッファが存在するかどうかによって異なります。読み取りモードまたは書き込みモードです。バッファーがどのモードであっても、容量の意味は常に同じです。

読み取りおよび書き込みモードの容量、位置、制限についての説明は図の後ろにあります。

capacity: 容量

メモリブロックとして、Buffer には「容量」とも呼ばれる固定サイズの値があり、容量 byte、long、char およびその他の型のみを書き込むことができます。バッファがいっぱいになると、データの書き込みを続行する前に (データの読み取りまたはデータのクリアによって) バッファを空にする必要があります。

position: 現在位置

バッファにデータを書き込むとき、position は現在位置を表します。初期位置値は 0 です。バイト、ロングなどのデータがバッファに書き込まれると、位置はデータを挿入できる次のバッファ ユニットに進みます。最大位置は容量 - 1 です。

データを読み取るときは、特定の位置からも読み取られます。バッファが書き込みモードから読み取りモードに切り替わると、位置は 0 にリセットされます。データがバッファの位置から読み取られると、位置は次の読み取り可能な位置に進みます。

limit: 書き込み可能/読み取り可能な最大位置

書き込みモードでは、バッファの制限は、バッファに書き込むことができるデータの最大量を示します。 書き込みモードでは、制限はバッファの容量と同じになります。
  • バッファを読み取りモードに切り替える場合、制限は読み取ることができるデータの最大量を示します。したがって、バッファを読み取りモードに切り替えると、書き込みモードの位置値に制限が設定されます。つまり、以前に書き込まれたすべてのデータを読み取ることができます (書き込みデータの数に制限が設定されており、この値は書き込みモードの位置です)

    3. バッファの種類
  • Java NIO には次のバッファの種類があります

  • ByteBuffer

  • MappedByteBuffer

  • CharBuffer

  • DoubleBuffer

  • FloatBuffer

  • IntBuffer

Buffer

ShortBuffer

ご覧のとおり、これらのバッファタイプは異なるものを表しますデータ型。つまり、バッファ内のバイトは、char、short、int、long、float、または double 型を通じて操作できます。
MappedByteBuffer は少し特殊であり、これに関連する特別な章で説明します。

4. バッファの割り当て
Buffer オブジェクトを取得するには、まずそれを割り当てる必要があります。 すべての Buffer クラスには、allocate メソッドがあります。以下は、容量 50 バイトの ByteBuffer を割り当てる例です。

ByteBuffer buf = ByteBuffer.allocate(50);
ログイン後にコピー

  • 5. バッファにデータを書き込む
  • バッファにデータを書き込むには 2 つの方法があります:

  • チャネルからバッファに書き込む。

Buffer の put() メソッドを通じて Buffer に書き込みます。

バッファを初期化するとき、バイト配列をバッファに入れます
🎜🎜
public void test1() throws FileNotFoundException {//初始化容量ByteBuffer buf1 = ByteBuffer.allocate(48);//通过数组初始化,并将数组中的值放入缓冲区byte[] bytes = "123".getBytes();
        ByteBuffer buf2 = ByteBuffer.wrap(bytes);//将通道中的读到缓冲区int bytesRead = channel.read(bf);//通过put方法写入缓冲区,put有很多重载        buf1.put(bytes);
    }
ログイン後にコピー
🎜🎜🎜🎜🎜

put方法有很多版本,允许你以不同的方式把数据写入到Buffer中。例如, 写到一个指定的位置,或者把一个字节数组写入到Buffer。 

flip()方法

flip方法将Buffer从写模式切换到读模式。调用flip()方法会将position设回0,并将limit设置成之前position的值。

换句话说,position现在用于标记读的位置,limit表示之前写进了多少个byte、char等 —— 现在能读取多少个byte、char等。

六、从Buffer中读取数据

从Buffer中读取数据有两种方式:

  1. 从Buffer读取数据到Channel。

  2. 使用get()方法从Buffer中读取数据。

        //将缓冲区的数据写入通道        channel.write(buf1);//通过get方法获取缓冲区中数据 get有很多重载buf1.get();
ログイン後にコピー

 

 

get メソッドには多くのバージョンがあり、さまざまな方法でバッファからデータを読み取ることができます。たとえば、指定された位置から読み取るか、バッファからバイト配列にデータを読み取ります。

7. rewind() メソッド: 位置をリセット

Buffer.rewind() は位置を 0 に戻すので、バッファー内のすべてのデータを再読み取りできます。制限は変更されず、バッファから読み取れる要素 (バイト、文字など) の数を示します。

8. Clear() メソッドと Compact() メソッド

バッファー内のデータが読み取られた後、バッファーを再び書き込む準備ができている必要があります。これは、clear() メソッドまたは Compact() メソッドを介して実行できます。

clear()メソッドが呼び出されると、positionは0に戻り、limitはcapacityの値に設定されます。つまり、バッファがクリアされます。バッファ内のデータはクリアされませんが、これらのマークは、バッファへのデータの書き込みを開始する場所を示します。

バッファーに未読のデータがある場合、clear() メソッドを呼び出します。データは「忘れられます」。つまり、どのデータが読み取られ、どのデータが読み取られていないのかを示すマーカーが存在しなくなります。

バッファ内にまだ読み取られていないデータがあり、そのデータが後で必要になるが、最初にデータを書き込みたい場合は、compact() メソッドを使用します。

compact() メソッドは、すべての未読データをバッファーの先頭にコピーします。次に、位置を最後の未読要素のすぐ後ろに設定します。制限属性は引き続き、clear() メソッドと同様に容量に設定されます。これでバッファはデータを書き込む準備が整いましたが、読み取られていないデータは上書きされません。

9. Mark() メソッドとreset() メソッド: 位置をマークし、位置を返す

Buffer.mark() メソッドを呼び出すことで、バッファ内の特定の位置をマークできます。後で Buffer.reset() メソッドを呼び出すことで、この位置に復元できます。例:

10.quals() メソッドと CompareTo() メソッド

2 つのバッファーを比較するには、equals() メソッドと CompareTo() メソッドを使用できます。

equals()

次の条件が満たされる場合、それは 2 つのバッファーが等しいことを意味します:

  1. は同じ型 (byte、char、int など) を持ちます。

  2. バッファ内の残りのバイト、文字などの数は等しい。

  3. バッファ内の残りのバイト、文字などはすべて同じです。

ご覧のとおり、equals はバッファ内のすべての要素ではなく、バッファの一部のみを比較します。実際には、バッファ内の残りの要素を比較するだけです。

compareTo() メソッド

compareTo() メソッドは、2 つのバッファーの残りの要素 (byte、char など) を比較します。次の条件が満たされる場合、一方のバッファーは他方のバッファーより「小さい」とみなされます。

最初のものは、等しくない要素が別のバッファ内の対応する要素より小さいです。
  1. すべての要素は等しいですが、最初のバッファーが他のバッファーよりも先に使い果たされます (最初のバッファーの要素は他のバッファーよりも少ない)。
  2. (注釈: 残りの要素は位置から限界までの要素です)

2. バッファーのスキャッター/ギャザー

いわゆるスキャッターとギャザーは複数のバッファーに対応するチャンネルです: 1 つのチャンネルを複数のバッファーに読み込みます。キャッシュ; 複数のキャッシュを 1 つのチャネルに書き込みます

Java NIO は、スキャッター/ギャザリングをサポートし始めます。

チャネルからのスキャッタ読み取りとは、読み取り操作中に読み取りデータを複数のバッファに書き込むことを意味します。したがって、チャネルは、チャネルから読み取られたデータを複数のバッファに「分散」します。チャネルへの収集書き込みは、書き込み操作中に複数のバッファから同じチャネルにデータを書き込むことを意味します。それらをチャネルに送信します。

Scatter / Gather は、送信されるデータを個別に処理する必要がある場合によく使用されます。たとえば、メッセージ ヘッダーとメッセージ本文で構成されるメッセージを送信する場合、メッセージ本文とメッセージ ヘッダーを別のバッファーに分散することができます。これにより、メッセージ ヘッダーとメッセージ本文を簡単に処理できるようになります。

分散読み取り


分散読み取りとは、データが 1 つのチャネルから複数のバッファーに読み取られることを意味します。以下で説明します:

Java NIO: Scattering Read

Java NIO: Scattering Read

注意buffer首先被插入到数组,然后再将数组作为channel.read() 的输入参数。read()方法按照buffer在数组中的顺序将从channel中读取的数据写入到buffer,当一个buffer被写满后,channel紧接着向另一个buffer中写。

Scattering Reads在移动下一个buffer前,必须填满当前的buffer,这也意味着它不适用于动态消息(译者注:消息大小不固定)。换句话说,如果存在消息头和消息体,消息头必须完成填充(例如 128byte),Scattering Reads才能正常工作。

Gathering Writes

Gathering Writes是指数据从多个buffer写入到同一个channel。如下图描述:

Java NIO: Gathering Write

Java NIO: Gathering Write

 

buffers数组是write()方法的入参,write()方法会按照buffer在数组中的顺序,将数据写入到channel,注意只有position和limit之间的数据才会被写入。因此,如果一个buffer的容量为128byte,但是仅仅包含58byte的数据,那么这58byte的数据将被写入到channel中。因此与Scattering Reads相反,Gathering Writes能较好的处理动态消息

    ByteBuffer header = ByteBuffer.allocate(128);
    ByteBuffer body   = ByteBuffer.allocate(1024);
    ByteBuffer[] bufferArray = { header, body };
    channel.read(bufferArray);  //传入Buffer数组即可//方便展示、直接写,写之前要反转bufferchannel.write(bufferArray);
ログイン後にコピー

 

以上がJAVAでのバッファの使用法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

関連ラベル:
ソース:php.cn
このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート