6

私は頻繁にテキストをファイルに出力します。私は何か疑問に思っています: どのように機能しBufferedWriterますか?

を呼び出すと、ファイルにテキストが書き込まれますwriter.write(text)か? テキストを書き込まない場合、フラッシュ関数を使用してデータを書き込む必要がありますか?

例えば:

       File file = new File("statistics.txt");
        if (!file.exists()) {
            file.createNewFile();
        }
        else
        {
            file.delete();
            file.createNewFile();
        }
        FileWriter fileWritter = new FileWriter(file.getAbsoluteFile(),true);
        BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
        Iterator<Map.Entry<String,Token>> it = listofTakenPairMap.entrySet().iterator();
        int isim_isim=0;
        int isim_fiil=0;
        int zarf_fiil=0;
        while (it.hasNext()) {
            @SuppressWarnings("rawtypes")
            Map.Entry pairs = (Map.Entry)it.next();
            Token token=(Token)pairs.getValue();
            String str=pairs.getKey()+ " = " +token.getCount();
            if(token.getTypeOfPairofToken()==0){//isim-isim
                isim_isim+=token.getCount();
            }
            else if(token.getTypeOfPairofToken()==1){
                isim_fiil+=token.getCount();
            }
            else{ //zarf-fiil
                zarf_fiil+=token.getCount();
            }
            System.out.println(str);
            bufferWritter.write(str);
            bufferWritter.newLine();
            //it.remove(); // avoids a ConcurrentModificationException
        }
        bufferWritter.newLine();
        bufferWritter.write("##############################");
        bufferWritter.newLine();
        bufferWritter.write("$isim_isim sayisi :"+isim_isim+"$");
        bufferWritter.newLine();
        bufferWritter.write("$isim_fiil sayisi :"+isim_fiil+"$");
        bufferWritter.newLine();
        bufferWritter.write("$zarf_fiil sayisi :"+zarf_fiil+"$");
        bufferWritter.newLine();
        bufferWritter.write("##############################");
        bufferWritter.flush();
        bufferWritter.close();

while ループでエラーが発生すると、データを書き込まずにファイルを閉じます。flushwhile ループで関数を使用する場合、なぜ使用する必要があるのBufferedWriterでしょうか? 間違っている場合は修正してください。

4

3 に答える 3

13

定義上、バッファ付きライターはデータをバッファリングし、メモリに十分な量がある場合にのみ書き込むことで、ファイル システムへのラウンドトリップが多すぎるのを回避します。

例外を適切に処理し、常に行う必要があるように最終ブロックでストリームを閉じると、バッファーがディスクにフラッシュされ、これまでにバッファーされたライターに書き込まれたすべてがディスクに書き込まれます (もちろん例外正確にはディスクへの書き込みエラーが原因です)。

したがって、解決策は、書き込むたびにフラッシュしないことです。これは、バッファされたライターの目的を無効にするためです。解決策は、finally ブロックで閉じることです (または、それを行う Java 7 の trye-with-resources ステートメントを使用します)。

于 2013-01-22T16:10:02.070 に答える
2

ストリーム内のデータは、ブロック単位でディスクに書き込まれます。OutputStreamそのため、またはに何かを書き込むときにWriter、サーバーが自動的にディスクに永続化されるとは思わないでください。これは実際にはほとんど行われません。プロセスは、仮想マシンおよびホスト オペレーティング システム内の小さなプロセスにすぎません。

データをディスクに書き込む場合は、ディスク I/O が完了するまで待つ必要があります。その間、コードは実行されませんが、待機しています。これにより、サービス時間が増加します。

また、頻繁なディスク書き込み (平均flush()) は、ブロックの内容全体を単純に上書きすることはできず、同じブロックを何度も更新する必要があるため、システムに大きな負荷をかけます。

それが、Java のような言語がバッファリングを導入した理由です。

あなたの質問に答えるにはwrite()データを入力すると、特定のレベルまでバッファリングされます(バッファがいっぱいになるまで)。その後、永続化されます (基になるStreamに書き込まれます。たとえばFileOutputStream)。flush()またはを呼び出すとclose()、バッファが空になるため、バッファリングされたすべてのバイトが基になる に書き込まれStreamます。また、その Streamのflush()orメソッドも呼び出します。close()

Exceptionループ内で が発生した場合、ストリームを閉じないため、一部のデータが失われる可能性があります。try { } catch (IOException ex) {}ストリームを適切に囲み、閉じます。

于 2013-01-22T16:10:28.940 に答える
1

私は頻繁にテキストをファイルに出力します。私は何か疑問に思っています: どのように機能し BufferedWriterますか?

jdkのソースコードを自分で確認してください

writer.write(text) を呼び出すと、ファイルにテキストが書き込まれますか? テキストを書き込まない場合、フラッシュ関数を使用してデータを書き込む必要がありますか?

いいえ。 を呼び出すたびにwrite(String s)、次のように呼び出します。write(str, 0, str.length());これは、openJDK のソースからのソース コードです。

  218     public void write(String s, int off, int len) throws IOException {
  219         synchronized (lock) {
  220             ensureOpen();
  221 
  222             int b = off, t = off + len;
  223             while (b < t) {
  224                 int d = min(nChars - nextChar, t - b);
  225                 s.getChars(b, b + d, cb, nextChar);
  226                 b += d;
  227                 nextChar += d;
  228                 if (nextChar >= nChars)
  229                     flushBuffer();
  230             }
  231         }
  232     }
  233      


  118     /**
  119      * Flushes the output buffer to the underlying character stream, without
  120      * flushing the stream itself.  This method is non-private only so that it
  121      * may be invoked by PrintStream.
  122      */
  123     void flushBuffer() throws IOException {
  124         synchronized (lock) {
  125             ensureOpen();
  126             if (nextChar == 0)
  127                 return;
  128             out.write(cb, 0, nextChar);
  129             nextChar = 0;
  130         }
  131     }    

ご覧のとおり、直接書き込みません。の場合のみif (nextChar >= nChars)、バッファ自体をフラッシュします (デフォルトではprivate static int defaultCharBufferSize = 8192;、その「ラッピング」クラスを使用します。(Java では、Java IO は Decorator Design Pattern を使用して設計されています。最終的には、 を呼び出しwrite(char[] chars, int i, int i1)ます)。

while ループでエラーが発生すると、データを書き込まずにファイルを閉じます。while ループでフラッシュ関数を使用する場合、なぜ使用する必要があるのBufferedWriterでしょうか?

IO コストは非常に高価です。出力を「オンザフライ」で表示する必要がない限り (たとえば、最新の更新でいつでもログを表示するなど)、自動的に実行してパフォーマンスを向上させる必要があります。

于 2013-01-27T09:55:44.557 に答える