JAvaにおけるNIOのまとめ

6917 ワード

1、NIOとは
NIOはNew IOで、このライブラリはJDK 1です.4に導入されたばかりです.NIOとIOは同じ役割と目的を持っているが、実現方式が異なり、NIOは元のI/Oの不足を補い、標準Javaコードで高速を提供し、NIOは主にブロックを使用するため、NIOの効率はIOよりずっと高い.
NIOとIOの最大の違いは、データのパッケージングと伝送方式です.IOはストリームでデータを処理し、NIOはブロックでデータを処理する.
ストリーム向けIOは1バイトの処理データを一度に1バイトずつ処理し、1つの入力ストリームが1バイトを生成し、1つの出力ストリームが1バイト消費する.
ブロック向けIOシステムは、ブロック形式でデータを処理する.各操作は、1ステップで1つのデータブロックを生成または消費する.
次に、IOとNIOを使用してファイルの内容を簡単に読み取る例から、NIOの学習の旅に入ります.
IOを使用して、指定されたファイルの最初の1024バイトを読み取り、印刷します.
<span style="font-size:18px;">/** 
 *   IO        1024      。 
 * @param file       。 
 * @throws java.io.IOException IO  。 
 */  
public void ioRead(String file) throws IOException {  
    FileInputStream in = new FileInputStream(file);  
    byte[] b = new byte[1024];  
    in.read(b);  
    System.out.println(new String(b));  
}  </span>

NIOを使用して読み込む
<span style="font-size:18px;">/** 
 *   NIO        1024      。 
 * @param file       。 
 * @throws java.io.IOException IO  。 
 */  
public void nioRead(String file) throws IOException {  
    FileInputStream in = new FileInputStream(file);  
    FileChannel channel = in.getChannel();  
  
    ByteBuffer buffer = ByteBuffer.allocate(1024);  
    channel.read(buffer);  
    byte[] b = buffer.array();  
    System.out.println(new String(b));  
}  </span>

以上の例から、NIOは、チャネルチャネルチャネルおよびバッファBufferに基づいてブロック向けIOデータ処理を実現していることが分かる.次に,NIOライブラリのコア概念と,高度な特性から下層プログラミングの詳細までのほとんどの面について議論し,学習する.
2、NIO基礎
BufferとChannelは標準NIOのコアオブジェクト(ネットワークNIOにはSelectorコアオブジェクトもある)であり、ほとんどのIO操作で使用されます.Channelは、元のIOストリームのシミュレーションであり、ソースおよび宛先データはいずれも1つのChannelオブジェクトを通過する必要があります.1つのBufferは実質的にコンテナオブジェクトであり、チャネルに送られたすべてのオブジェクトはBufferに先に置かなければならない.同様に、チャネルから読み込まれたデータはBufferに読み込まれます.
2.1 Bufferの紹介
Bufferは、書き込みまたは読み出しのデータを含むオブジェクトです.NIOではbufferオブジェクトにデータを入れますが、IOではStreamオブジェクトに直接書き込んだり読み込んだりします.アプリケーションは、チャネルを直接読み書きするのではなく、Bufferによって行う必要があります.すなわち、チャネルはBufferによってデータを読み書きする必要があります.NIOでは、すべてのデータはBufferで処理され、NIOがデータを読み書きする中継プールです.
Bufferを使用してデータを読み書きするには、一般的に次の4つの手順に従います.
Bufferにデータを書き込みます.
flip()メソッドを呼び出す.
Bufferからデータを読み込む.
clear()メソッドまたはcompact()メソッドを呼び出します.
Bufferにデータを書き込むと、どのくらいのデータが書かれているかが記録されます.データを読み込むには、flip()メソッドでBufferを書き込みモードから読み取りモードに切り替える必要があります.読み出しモードでは、Bufferに書き込まれたすべてのデータを読み出すことができます.すべてのデータを読み終えると、バッファを空にして、再び書き込むことができるようにする必要があります.バッファを空にするには、clear()メソッドまたはcompact()メソッドを呼び出す2つの方法があります.clear()メソッドはバッファ全体を空にします.compact()メソッドでは、すでに読んだデータのみが消去されます.未読データはすべてバッファの先頭に移動され、新しく書き込まれたデータはバッファ未読データの後ろに配置されます.
Bufferには主に以下のものがある:ByteBuffer、charBuffer、DoubleBuffer、FloatBuffer、IntBuffer、LongBuffer、ShortBuffer.
2.3チャンネル紹介
Channelは、データの読み取りと書き込みを行うオブジェクトです.それをIOの中の流れと見なすことができます.しかし、ストリームとはいくつかの違いがあります.
チャンネルは双方向であり、読み書きも可能であり、ストリームは一方向のである.
Channelは、非同期の読み書きを行うことができる
チャネルの読み書きはbufferオブジェクトを通過しなければならない.
前述したように、すべてのデータはBufferオブジェクトによって処理されるので、Channelにバイトを直接書き込むことはありません.逆に、Bufferにデータを書き込むことです.同様に、チャネルからバイトを読み込むのではなく、チャネルからBufferにデータを読み込み、Bufferからバイトを取得します.
Java NIOでは主に次のようなタイプがあります.
FileChannel:ファイルからデータを読み込むDatagramChannel:UDPネットワークプロトコルデータの読み書きSocketChannel:TCPネットワークプロトコルデータの読み書きServerSocketChannel:TCP接続を傍受可能3、NIOでの読み書き
IOの読み取りと書き込みは、データとStream、NIOの読み取りと書き込みに対応し、チャネルとバッファに対応します.NIOでのチャネルからの読み込み:バッファを作成し、チャネルにデータをバッファに読み込みます.NIOはデータをチャネルに書き込む:バッファを作成し、データで埋め込み、チャネルにこれらのデータで書き込みを実行させる.
3.1ファイルから読み込む
NIOシステムでは、すべてのデータをBufferでカプセル化する必要があるため、ChannelからBufferにデータを読み込む必要があります.
したがって、ファイルからデータを読み込むには、次の3つのステップが必要です.
1)FileInputStreamからチャネルを取得する
2)Bufferの作成
3)チャネルからBufferへのデータの読み出し
具体的な手順を見てみましょう.
ステップ1:チャネルの取得
<span style="font-size:18px;">FileInputStream fin = new FileInputStream( "readandshow.txt" );
FileChannel fc = fin.getChannel();</span>

ステップ2:バッファの作成
<span style="font-size:18px;">ByteBuffer buffer = ByteBuffer.allocate( 1024 );</span>

ステップ3:チャネルからバッファにデータを読み込む
<span style="font-size:18px;"><pre name="code" class="java"><span style="font-family:SimSun;font-size:18px;">fc.read( buffer );</span></span>
 
 

3.2 写入数据到文件

类似于从文件读数据, 
第一步:获取一个通道

<span style="font-size:18px;">FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" );
FileChannel fc = fout.getChannel();</span>

ステップ2:バッファを作成し、データをバッファに入れる
<span style="font-size:18px;">ByteBuffer buffer = ByteBuffer.allocate( 1024 );
for (int i=0; i<message.length; ++i) {
 buffer.put( message[i] );
}
buffer.flip();</span>

ステップ3:バッファデータをチャネルに書き込む
<span style="font-size:18px;">fc.write( buffer );</span>

4、注意すべき点
4.1検査状態
より多くのデータがない場合、コピーが完了してもread()メソッドは-1を返し、このメソッドに基づいて読み終わったかどうかを判断できます.
<span style="font-size:18px;">int r= fcin.read( buffer );
if (r==-1) {
     break;
     }</span>

4.2 Bufferクラスのflip、clearメソッド
buffer状態を制御する3つの変数
position:どのくらいのデータを書いたか、またはどのくらいのデータを読んだかを追跡します.次のバイトがどの位置から来たかを指します.
Limit:capacity以下の値を持つデータがどれだけ取り出せるか、または書き込むスペースがどれだけあるかを表します.
Capacity:バッファの最大容量を表し、一般的にバッファを新規作成する場合、limitの値とcapacityの値はデフォルトで等しくなります.
flip、clearの2つの方法は、これらの値を設定するために使用されます.
flipメソッド
まずflipのソースコードを見てみましょう.
<span style="font-size:18px;">public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
 }</span>

上記のFileCopyプログラムでは、データを書き込む前にbuffer.flip();メソッドを呼び出しました.このメソッドでは、現在のポインタ位置positionをlimitに設定し、現在のポインタpositionをデータの先頭に向け、バッファからチャネルにデータを書き込むことができます.positionは0に設定され、これは私たちが得た次のバイトが最初のバイトであることを意味します.limitは元のpositionに設定されています.これは、以前に読んだすべてのバイトが含まれており、1バイトも多くないことを意味します.
clearメソッド
まずclearのソースコードを見てみましょう.
<span style="font-size:18px;"> public final Buffer clear() {
    position = 0;
    limit = capacity;
    mark = -1;
    return this;
}</span>

上記のFileCopyプログラムでは、データが書き込まれた後、つまりデータが読み出される前に、より多くのバイトを受信するためにバッファを再設定するbuffer.clear();メソッドを呼び出した.上図はclear()が呼び出された後のバッファの状態を示しています.