前の記事の隣で、Javaでバイトストリーム操作を学び続けます。
デコレーターバッファーストリームBufferedInput/outputStream
デコレーターストリームは、実際には設計パターン「デコレーターモード」に基づいたファイルIOストリームであり、バッファストリームはその1つにすぎません。見てみましょう。
この前に、ディスクバイトまたはバイトからの読み取りと書き込みの両方で、ファイルの読み取りおよび書き込みfileinputStreamとfileoutputStreamを使用しました。これは非常に時間がかかります。
バッファストリームは、一度にディスクからメモリに指定された容量のバイト数を事前読み取りでき、その後の読み取り操作はメモリから直接読み取り、効率を向上させます。バッファリングストリームの特定の実装を見てみましょう。
BufferedInputStreamを最初に例として取り上げましょう。そのコアプロパティについて簡単に言及しましょう。
BUFは、読み取りバッファリングに使用されるバイト配列です。ストリームが読み取られると、その値は継続的に埋められ、その後の読み取り操作は、このバッファーアレイに直接基づいています。
default_buffer_sizeデフォルトのバッファーのサイズ、つまりbufの配列長を指定します。 max_buffer_sizeバッファの上限を指定します。
カウントは、バッファーアレイの最後の有効なバイトインデックスを指します。 POSは、読み取る次のバイトインデックス位置を指します。
MarkposとMarklimitは、読み取り操作を繰り返すために使用されます。
次に、BufferedInputStreamのいくつかの例のコンストラクターを見てみましょう。
public bufferedinputStream(inputstream in){this(in、default_buffer_size);} public bufferedinputStream(inputstream in、int size){super(in); if(size <= 0){新しいIllegalargumentException( "バッファーサイズ<= 0"); } buf = new byte [size];}全体として、前者は「装飾」された入力ストリームインスタンスで渡し、デフォルトサイズのバッファーを使用する必要があります。後者は、バッファーのサイズを明示的に示すことができます。
さらに、Super(in)は、このinputStreamインスタンスを親クラスFilterInputStreamの属性フィールドに保存し、すべての実際のディスク読み取り操作がこのinputStreamインスタンスによって発行されます。
最も重要な読み取り操作とバッファの充填方法を見てみましょう。
public同期int read()throws ioexception {if(pos> = count){fill(); if(pos> = count)return -1; } return getBufifopen()[pos ++]&0xff;}誰もがこの方法にすでに精通していると思います。ストリームから次のバイトを読み取り、返しますが、詳細の実装はまだわずかに異なります。
カウントは、バッファーアレイの有効なバイトインデックスの次の位置を指し、POSは読み取られるバイトインデックスの次の位置を指します。理論的には、POSはカウントよりも大きくすることはできません。
POがカウントに等しい場合、バッファアレイ内のすべての有効なバイトが読み取られていることを意味します。現時点では、バッファ内の「役に立たない」データを破棄する必要があり、バッファを埋めるためにディスクから新しいデータのバッチがリロードされます。
実際、充填方法はそれが行うことです。それはたくさんのコードを持っているので、私はあなたを解析するためにあなたを連れて行きません。その機能を理解している場合、その実装を分析するのはおそらく簡単です。
fillメソッドが呼び出された後もPOSがカウントに等しい場合、inputstreamインスタンスがストリームからデータを読み取っていないことを意味します。つまり、ファイルストリームに読み取るデータはありません。この場合、塗りつぶしメソッドの行246を参照してください。
一般に、バッファが正常に埋められた場合、読み取り方法はバッファから直接バイトを取り、それを発信者に返します。
public synchronized int read(byte b []、int off、int len){// .....}この方法は「知人」でもあり、不必要な説明はもはやありません。実装は類似しています。
SKIPメソッドは、ファイルストリームを継続的に読み取るために指定された長さのバイト数をスキップするために使用されます。
パブリックシンクロナイズドロングスキップ(ロングn){// ......}注意すべきことの1つは、スキップ方法がnバイトをスキップしようとするが、nバイトをスキップすることは保証されていないことです。このメソッドは、スキップされた実際のバイト数を返します。バッファーアレイ内の使用可能なバイトの残りの数がN未満の場合、バッファーアレイでスキップできる実際のバイト数は最終的にスキップされます。
最後に、この密接な方法について話しましょう。
public void close()throws ioException {byte [] buffer; while((buffer = buf)!= null){if(bufupdater.compareandset(this、buffer、null)){inputstream input = in; in = null; if(input!= null)input.close();戻る; } //新しいbufがfill()でケースが付けられた場合にretry}}}閉じる方法は、「装飾された」ストリームを空にし、関連するリソースをリリースするためにその密接な方法を呼び出します。
BufferedInputStreamは読み取りバッファリング機能を提供しますが、BufferedOutputStreamは書き込みバッファリング機能を提供します。つまり、メモリ書き込み操作はすぐにディスクに更新されず、バッファーに一時的に保存され、バッファがいっぱいになると一緒に書き込まれます。
Protected byte buf [];保護されたintカウント。
BUFは内部バッファを表し、カウントはバッファー内の実際のデータ容量、つまりBUFアレイの長さではなく、BUFの有効バイトの数を表します。
public bufferedoutputStream(outputStream out){this(out、8192);} public bufferedOutputStream(outputStream out、int size){super(out); if(size <= 0){新しいIllegalargumentException( "バッファーサイズ<= 0"); } buf = new byte [size];}同じ実装のアイデアを使用すると、出力ストリーム出力ストリームインスタンスを提供する必要があり、バッファサイズもオプションで指定できます。
public同期void write(int b)throws ioexception {if(count> = buf.length){flushbuffer(); } buf [count ++] =(byte)b;}書き込み方法は、まずバッファーがこの書き込み操作に対応できるかどうかを確認します。ディスク書き込み操作を開始できない場合、すべてのバッファデータがディスクファイルに書き込まれます。そうしないと、バッファは最初にバッファーに書き込まれます。
もちろん、BufferedOutputStreamは、外側にインターフェイスを提供するフラッシュメソッドも提供します。つまり、ディスクにデータを書き込む前にバッファがいっぱいになるまで待つ必要はありません。また、この方法を明示的に呼び出して、バッファをクリアしてディスクファイルを更新することもできます。
public同期void flush()throws ioexception {flushbuffer(); out.flush();}バッファリングストリームに関しては、コアコンテンツが上記のように導入されます。これは、効率を大幅に改善できるストリームです。それにより、ディスクアクセスの数を減らし、プログラムの実行効率を改善できます。
Object Serialization Stream ObjectInput/OutputStreamと、基本タイプに基づいてデコレーターストリームDatainput/outputStreamについては説明しません。シリアル化を学ぶとき、これら2つのバイトストリームについて再び説明します。
記事のすべてのコード、画像、ファイルは、私のgithubのクラウドに保存されます。
(https://github.com/singleyam/overview_java)
ローカルでダウンロードすることもできます。
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。