序文
前の記事では、ファイルタイプの抽象ディスクファイルを紹介しました。ディスクファイルまたはディレクトリを抽象的に説明するためにのみ使用されますが、ファイルのコンテンツにアクセスして変更する機能はありません。
Java IOストリームは、ファイルの内容の読み取りと書き込みに使用されるデザインです。出力ディスクファイルのコンテンツのメモリまたは出力メモリデータをディスクファイルに出力するデータ転送を完了できます。
Java IOストリームのデザインは完璧ではありません。 IOストリームの理解を高めている多くのクラスを設計しましたが、2つの主要なカテゴリのみがあります。1つはバイナリファイルのバイトストリームで、もう1つはテキストファイルの文字ストリームです。この記事では、関連するバイトストリームの原則と使用シナリオを最初に学びます。主に関係する特定のストリームタイプは次のとおりです。
基本クラスのバイトストリーム入力/出力ストリーム
InputStreamとoutputStreamは、それぞれバイトストリームを読み取り、バイトストリームを作成するためのベースクラスです。すべてのバイト関連のストリームは、それらのいずれかから継承する必要があります。抽象クラスとして、彼らはまた、最も基本的な読み取りおよび書き込み操作を定義します。見てみましょう:
例としてinputstreamを取ります:
public abstract int read()throws ioException;
これは抽象的な方法であり、デフォルトの実装を提供しないため、サブクラスを実装する必要があります。この方法の目的は、現在のファイルの次のバイトを返すことです。
もちろん、このメソッドの返品値は整数タイプ「int」を使用して受信されることもわかります。そのため、「バイト」を使用してみませんか?
まず、読み取り方法によって返される値は8ビットのバイナリでなければならず、8ビットのバイナリで取得できる値間隔は「0000 0000、1111 1111」、つまり範囲[-128、127]です。
また、読み取り方法は、ファイルが最後まで読み取られると、つまり、ファイルに次のバイトが読み取られていない場合、値-1が返されることも指定します。バイトが戻り値のタイプとして使用されている場合、メソッドが-1を返す場合、これがファイル内のデータコンテンツなのか、ストリームの終わりかを判断する必要がありますか?
INTタイプは4つのバイトを占め、ハイビットの3つのバイトはすべて0です。最低ビットバイトのみを使用します。ストリームフラグの端に遭遇すると、データを表す値-1(24 0 + 8 1s)とは自然に異なる4バイトで表される-1(32 1s)を返します。
次は読み取り方法でもありますが、inputstreamはデフォルトの実装を提供します。
public int read(byte b [])throws ioexception {return read(b、0、b.length);} public int read(byte b []、int off、int len)throws ioexception {//これらの2つの方法は本質的に同じです。最初の方法は2番目のメソッドの特別な形式であり、バイトの配列を渡すことができ、アレイインデックス位置0から始まるファイルで読み取られたバイトを埋めるためにプログラムを埋めるために、配列の長さのバイト数を記入する必要があります。
2番目の方法は少し広いため、開始位置とバイトの総数を指定できます。
inputstreamには他にもいくつかの方法がありますが、基本的には詳細に実装されていません。簡単に見てみましょう。
マークメソッドは、現在のストリームリーディング位置のフラグをマークし、リセットメソッドは読み取りポインターをフラグへのリセットします。
実際、ファイルの読み取りのために読み取りをリセットすることは不可能ですが、一般に、フラグの位置とリセットポイントの間のすべてのバイトが一時的に保存されます。リセットメソッドが呼び出されると、実際に保存された一時的なバイトセットから読み取りが繰り返されるため、最大キャッシュ容量を制限するためにReadLimitが使用されます。
マークサポートされたメソッドは、現在のストリームがこの「フォールバック」読み取り操作をサポートするかどうかを判断するために使用されます。
outputStreamとinuptStreamは類似していますが、1つが書かれており、もう1つが読み取られていることを除いて。ここでは繰り返しません。
ファイルバイトストリームfileinput/outputStream
私たちはまだFileInputStreamに焦点を合わせており、FileOutputStreamは似ています。
まず、FileInputStreamには、オブジェクトをインスタンス化するための次のコンストラクターがあります。
public fileInputStream(String name)throws filenotFoundException {this(name!= null?new file(name):null);} public fileinputStream(ファイルファイル)filenotFoundExceptionをスロー{string name =(file!= null?file.getPath():null); SecurityManager security = system.getSecurityManager(); if(security!= null){security.checkread(name); } if(name == null){新しいnullpointerexception(); } if(file.isinvalid()){new filenotfoundexception( "invalid file path"); } fd = new filedescriptor(); fd.attach(this); path = name; open(name);}これらの2つのコンストラクターは本質的に同じで、前者は後者の特別な形です。実際、後者の方法を見ないでください。そのほとんどは、セキュリティ検証を行っているだけです。コアはオープンメソッドで、ファイルを開くために使用されます。
主にこれら2つのコンストラクターは、ファイルが存在しない場合、またはファイルパスと名前が違法である場合、FilenotFoundExceptionがスローされます。
すべてのサブクラスを実装する必要があるベースクラスの入力ストリームに抽象的なメソッドが読まれ、FileInputStreamがローカルメソッドを使用して実装されることを忘れないでください。
public int read()throws ioexception {return read0();} private native int0()throws ioexception;当面の間、read0の特定の実装を調査する方法はありませんが、この読み取りメソッドの関数を使用して、ストリーム内の次のバイトを返すために使用され、-1を返す必要があります。これは、ファイルの最後まで読み取られ、読み取るバイトがないことを意味します。
さらに、FileInputStreamには他にも読み取り関連の方法がいくつかありますが、それらのほとんどはローカルメソッドを使用して実装されています。ここを見てみましょう:
FileInputStreamの内部方法は基本的にこのようなものであり、当面は使用できない高度で複雑な方法がいくつかあります。後で学びます。ファイルの読み取りの例を簡単に見てみましょう。
public static void main(string [] args)throws ioexception {fileinputStream input = new FileInputStream( "c://users//yanga//desktop//test.txt"); byte [] buffer = new byte [1024]; int len = input.read(buffer); string str = new String(バッファー); System.out.println(str); System.out.println(len); input.close();}出力の結果は非常に簡単です。テストファイルのコンテンツと実際のバイト数が読み取られますが、慎重な学生が見つけると、テストファイルのコンテンツが1024バイトを超えないようにするにはどうすればよいですか?
ファイルの内容を完全に読み出すために、1つのソリューションは、ファイルのすべての内容を可能な限り保存するのに十分な大きさのバッファーを定義することです。
この方法は、ファイルの実際のサイズを読み取ることが不可能であるため、明らかに望ましくありません。単純に特大のバイト配列を作成することは非常に悪い解決策です。
2番目の方法は、ダイナミックバイト配列ストリームを使用することです。これにより、内部バイト配列のサイズを動的に調整して適切な容量を確保できます。
FileOutputStreamに関して、もう1つ強調すべきことは、次の2つのコンストラクターを備えたコンストラクターです。
public fileoutputStream(string name、boolean append)public fileoutputStream(file file、boolean append)
パラメーターの追加は、このストリームの書き込み操作が上書きまたは追加されているかどうかを示します。
bytearrayinput/outputStream
いわゆる「バイトアレイストリーム」は、バイト配列を中心に動作するストリームです。他のストリームのようにファイルにストリームを読み取り、書き込みません。
バイト配列ストリームはファイルベースのストリームではありませんが、内部にカプセル化されたバイト配列は固定されていないが動的に拡張可能であり、多くの場合、非常に適した特定のシナリオに基づいているため、非常に重要なストリームです。
bytearrayinputStreamは、次のコンストラクターによってインスタンス化できる読み取りバイト配列のストリームです。
Protected byte buf []; Protected int pos; protected int count; public bytearrayinputStream(byte buf []){this.buf = buf; this.pos = 0; this.count = buf.length;} public bytearrayinputStream(byte buf []、int offset、int length)BUFは、ByTearRayInputStream内にカプセル化されたバイト配列です。 BytearrayinputStreamのすべての読み取り操作は、それを中心に回転しています。
したがって、bytearrayinputStreamオブジェクトをインスタンス化する場合、少なくとも1つのターゲットバイト配列が渡されます。
POS属性は、現在のストリームの読み取りの位置を記録するために使用され、Countはターゲットバイト配列の最後の有効なバイトインデックスの後者の位置を記録します。
これを理解した後、それを読むためのさまざまな方法を読むことは難しくありません:
//次のバイトパブリック同期read(){return(pos <count)? (buf [pos ++]&0xff):-1;} //レンバイトを読み取り、バイトアレイBパブリック同期read(byte b []、int off、int len){//同じ長さ、誰もが自分のjdkをチェックします}さらに、bytearrayinputStreamは、「繰り返し読み取り」操作を非常に簡単に実装します。
public void mark(int readaheadlimit){mark = pos;} public synchronized void reset(){pos = mark;}ByTearRayInputStreamはバイト配列に基づいているため、すべての繰り返される読み取り操作は実装が容易であり、インデックスに基づいて実装するのに十分です。
bytearrayoutputStreamは、記述されたバイト配列ストリームです。多くの実装にはまだ独自の特性があります。一緒に見てみましょう。
まず、これらの2つのプロパティが必要です。
保護されたバイトbuf []; //ここでのカウントは、BUF保護されたintカウントの有効なバイトの数を表します。
コンストラクタ:
public bytearrayoutputStream(){this(32);} public bytearrayoutputStream(int size){if(size <0){throw new IllegalArgumentException( "ネガティブ初期サイズ:"+サイズ); } buf = new byte [size];}コンストラクターのコアタスクは、内部バイトアレイBUFを初期化してサイズを渡すことができるようにして、初期化されたバイト配列サイズを明示的に制限することです。そうしないと、デフォルトの長さは32になります。
ByteArrayOutputStreamにコンテンツを外部から書き込む:
public同期Void write(int b){ensurecapacity(count + 1); buf [count] =(byte)b; count + = 1;} public synchronized void write(byte b []、int off、int len){if((off <0)||(off> b.length)||(len <0)||((off + len)-b.length> 0)){show new new indexoutofboundsexcection(); } ensurecapacity(count + len); System.ArrayCopy(b、off、buf、count、len); count += len;}それを見ると、すべての書き込み操作の最初のステップは、EnsureCapacityメソッドを呼び出すことです。目的は、現在のストリームのバイト配列がこの書き込み操作に対応できるようにすることです。
この方法も非常に興味深いです。内部BUFが計算後にこの書き込み操作をサポートできないことがわかった場合、成長方法は拡張のために呼び出されます。容量拡張の原理は、アレイリストの原理と類似しており、元の容量の2倍に拡張されます。
さらに、bytearrayoutputStreamにはwritetoメソッドもあります。
public同期されたvoid writeto(outputstream out)throws ioexception {out.write(buf、0、count);}内部にカプセル化されたバイト配列を出力ストリームに書き込みます。
残りの方法のいくつかも非常に一般的に使用されています。
これらの2つのストリームは「ストリーム」と呼ばれていますが、本質的に実際のストリームのようなリソースを割り当てることはないため、密接な方法を呼び出す必要はなく、それを呼ぶことは役に立たないことに注意してください(当局者は効果がないと述べています)。
テストケースはリリースされません。この記事で使用したすべてのコードケースを後でアップロードします。自分でダウンロードすることを選択できます。
長さを制御するために、残りの学習は次の記事に掲載されます。
記事のすべてのコード、画像、ファイルは、私のgithubのクラウドに保存されます。
(https://github.com/singleyam/overview_java)
ローカルでダウンロードすることもできます。
要約します
上記は、この記事のコンテンツ全体です。この記事の内容には、すべての人の研究や仕事に特定の参照値があることを願っています。ご質問がある場合は、メッセージを残してコミュニケーションをとることができます。 wulin.comへのご支援ありがとうございます。