JavaにおけるIOストリームの配列単位での遍歴が起こりやすい問題

9691 ワード

IOストリームで配列単位で読み取りやすいエラーを遍歴する
ガラガラ!IOストリームの連絡には通常配列単位の入力ストリームが使用されますが、このような入力ストリームについては、その内容を表示するには、遍歴にほかならないことを知っています.しかし、私たちが遍歴するとき、一つの問題を無視することがよくあります.次に、この問題を理解するために例を挙げてみましょう.例の中の異常については、まず投げ出し処理をします.直接重点を見たいなら、このコードをスキップして次のいくつかの小さなコードを見ることができます.
import java.io.File;
import java.io.FileReader;
import java.io.IOException;

public class Demo[
    public static void main(String[] args) throws IOException {
        //1.      
        File fie = new File("hello.txt");//          
        //2. FileReader   
        FileReader fr = new FileReader(file);//                  (     )
        //3.       
        char[] cbuf = new char[4];
        int len = fr.read(cbuf);
        //             
        while(len != -1){ //    fr.read(cbuf)           
            //    
            /*for(int i = 0; i < cbuf.length(); i++){//        ,      i
            //   
            for(int i=0;i<len;i++){//    i
                System.out.print(cbuf[i]);
            }
            //   
            //String str = new String(cbuf,0,len);
            //System.out.print(str);
            len = fr.read();
        }
        //4.      
        fr.close();
    }
]

以上のプログラムでは,遍歴処理には2つの方法があり,もう1つは/**/注釈で誤った部分であることがわかる.
for(int i = 0; i < cbuf.length(); i++){//        ,      i
    System.out.print(cbuf[i]);
}

このコードをよく分析すると、なぜ間違っているのでしょうか.実は以上のコードで定義した文字配列は、cbufが4文字ずつ格納されるたびにfrの読み取り操作は、配列から要素を絶えず上書きすることに相当し、これは私たちが遍歴するたびに配列のすべての内容(すなわち4文字)を印刷するが、cbufという配列の中で毎回すべての要素が上書きされることは不可能である.簡単に言えば、私たちのファイルの中で「helloworld」であれば、hellの4つの文字はまず配列に埋め込まれ、次にoworの4つの文字で、私たちはまだ2つの文字が残っていることを知っています.彼ら2つが配列に埋め込まれた後、配列の内容は実はldの2つの文字だけではありません.この2つの文字はowを上書きしただけです.実はあと2つはカバーされたorなので、新しい配列がldorになっています.私たちが遍歴している間に自然に問題が発生します.
では、なぜこのコードに問題が発生しないのでしょうか.
for(int i=0;i<len;i++){//    i
    System.out.print(cbuf[i]);
}

このコードと前のエラーのコードの明らかな違いを見てみましょう.このコードのlenは,文字入力ストリームが読み出す文字の個数が変化するにつれて変化することが分かる.
int len = fr.read(cbuf);2文字しか読み取らない場合、ここのlenは2で、後ろに上書きされていない文字まで遍歴することはなく、自然と問題はありません.
食事を加える
上記のコードには、Stringのコンストラクタを利用してString文字列を直接newして、便利ではありませんが、上記のような問題に注意する必要があります.ここでは、文字列の最初の文字インデックスとある文字インデックスを設定する必要があります.つまり、どの部分の文字を取るべきかを規定する必要があります.この構成方法について、APIでは、このように記述されている
/**
     * Allocates a new {@code String} that contains characters from a subarray
     * of the character array argument. The {@code offset} argument is the
     * index of the first character of the subarray and the {@code count}
     * argument specifies the length of the subarray. The contents of the
     * subarray are copied; subsequent modification of the character array does
     * not affect the newly created string.
     *
     * @param  value
     *         Array that is the source of characters
     *
     * @param  offset
     *         The initial offset
     *
     * @param  count
     *         The length
     *
     * @throws  IndexOutOfBoundsException
     *          If the {@code offset} and {@code count} arguments index
     *          characters outside the bounds of the {@code value} array
     */

文字配列パラメータのサブワードを含む新しいStringを割り当てます.offsetパラメータは、サブアレイの最初の文字とインデックスcountパラメータがサブアレイの長さを指定するものである.サブアレイのコンテンツはコピーされる.文字配列の後続の変更は、新しく作成された文字列には影響しません.
PARAMS:値-配列、文字のソースオフセット-初期オフセットカウント-長さ放出:IndexOutOfBoundsException-offsetとcountパラメータの境界外のインデックス文字value配列の外部と推定のコメント:String:@org.jetbrains.annotations.contract(純=真)パラメータvalue:@org.jetbrains.annotations.NotNull
その中の異常に対して私が処理していない原因は私がみんなにもっと直観的に肝心な内容を見ることができるようにしたいためで、コードは純粋な手書きで問題が発生するのは避けられないので、また指摘して、大物は噴き出さないでください
続きはIOストリームに関する様々な問題を更新し続けます.ありがとうございます.