web-dev-qa-db-ja.com

BufferedWriterがすべてを出力ファイルに書き込まない

Javaプログラムは、ファイルからテキストを1行ずつ読み取り、新しいテキストを出力ファイルに書き込みます。しかし、BufferedWriterに書き込むすべてのテキストではありませんプログラムが終了した後、出力ファイルに表示されます。

詳細:プログラムはCSVテキストドキュメントを取得し、それをSQLコマンドに変換して、データをテーブルに挿入します。テキストファイルには、次のような10000行以上が含まれています。

2007,10,9,1,1,1006134,19423882

プログラムは、ファイルをSQLファイルに出力する新しいSQLステートメントを作成する途中でランダムに停止することを除いて、正常に動作するようです。次のようになります。

insert into nyccrash values (2007, 1, 2, 1, 4, 1033092, 259916);
insert into nyccrash values (2007, 1, 1, 1, 1, 1020246, 197687);
insert into nyccrash values (2007, 10, 9, 1

これは、約10000行後に発生しますが、ファイルの終わりまでに数百行あります。ブレークが発生する場所は、1,の間です。ただし、142に変更すると、新しいファイルに最後に書き込まれるのは4であり、その整数から2が切り捨てられるため、文字は重要ではないようです。 。そのため、読者または作家は、一定量の書き込み/読み取りを行った後に死にかけているに違いないようです。

My Javaコードは次のとおりです。

import Java.io.*;

public class InsertCrashData
{
    public static void main (String args[])
    {
        try
        {   
            //Open the input file.
            FileReader istream = new FileReader("nyccrash.txt");
            BufferedReader in = new BufferedReader(istream);
            //Open the output file.
            FileWriter ostream = new FileWriter("nyccrash.sql");
            BufferedWriter out = new BufferedWriter(ostream);
            String line, sqlstr;

            sqlstr = "CREATE TABLE nyccrash (crash_year integer, accident_type integer, collision_type integer, weather_condition integer, light_condition integer, x_coordinate integer, y_coordinate integer);\n\n"; 
            out.write(sqlstr);

            while((line = in.readLine())!= null)
            {
                String[] esa = line.split(",");
                sqlstr = "insert into nyccrash values ("+esa[0]+", "+esa[1]+", "+esa[2]+", "+esa[3]+", "+esa[4]+", "+esa[5]+", "+esa[6]+");\n";
                out.write(sqlstr);
            }
        }
        catch(Exception e)
        {
            System.out.println(e);
        }
    }
}
28
golmschenk

残りのデータをフラッシュするOutputStreamを閉じる必要があります。

out.close();

BufferedWriterのデフォルトのバッファサイズは 8192文字 で、何百行もの未書き込みデータを簡単に保持できる大きさです。

63
Reimeus

あなたmustclose() your BufferedWriterclose() your BufferedWriterはIS-A Writer であるため、 AutoCloseable を実装する必要があります。 、つまり(強調が追加された)

不要になったときに閉じなければならないリソース。

flush()を呼び出す前にBufferedWriterに対して最初に close() を呼び出す必要があると言う人もいます。彼らは間違ってる。 BufferedWriter.close()のドキュメントでは、「ストリームを閉じ、最初にフラッシュする」と強調されています(強調を追加)。

文書化されたフラッシュのセマンティクス( flush() )は

基礎となるストリームにバッファリングされた出力を書き込むことにより、このストリームをフラッシュします

そのため、closeを使用する必要があり、closeはバッファリングされた出力をフラッシュします。

出力ファイルには、BufferedWriterに書き込んだテキストの一部が含まれていません。これは、そのテキストの一部がバッファーに保存されているためです。 BufferedWriterはそのバッファを空にせず、ファイルに渡します。


Java 7なので、AutoCloseableなどのBufferedWriterリソースが不要になったときに閉じられるようにする最善の方法は、自動リソースを使用することです管理(ARM)、別名 try-with-resources

 try (BufferedWriter out = new BufferedWriter(new FileWriter(file))) {
    // writes to out here
 } catch (IOException ex) {
    // handle ex
 }

closeが不要になったらBufferedReaderする必要もあるため、try-with-resourcesブロックをネストする必要があります。

 try (BufferedReader in = new BufferedReader(new FileReader("nyccrash.txt")) {
    try (BufferedWriter out = new BufferedWriter(new FileWriter("nyccrash.sql"))) {
       // your reading and writing code here
    }
 } catch (IOException ex) {
    // handle ex
 }
9
Raedwald

不要になったときに閉じる必要があるリソース。

_finally {
    out.close();//this would resolve the issue
    }
_

考慮すべき事項:

  • BufferedWriter.close()バッファを基礎となるストリームにフラッシュします。したがって、flush()を忘れて閉じない場合、ファイルにはすべてが含まれない可能性がありますあなたがそれに書いたテキスト。
  • BufferedWriter.close()は、ラップされたWriterも閉じます。これがFileWriterの場合、これは最終的にFileOutputStream を閉じ、ファイルへの書き込みが完了したことをOSに通知します。
  • ガベージコレクターは、BufferedWriterまたはラップされたFileWriterではなく、FileOuputStreamでclose()を自動的に呼び出します。 OSは幸せになりますが、GCを待つ必要があります。
  • ただし、OSリソースが不要になったらすぐにリリースする必要があります。これは、開いているファイル、データベース接続、印刷キューなどに当てはまります。これを信じて。
  • BufferedWriter.close()は内部文字バッファをクリアするため、BufferedWriter自体がスコープ内に残っている場合でも、ガベージコレクションにメモリを使用できます。

つまり、リソースの使用が終わったら、ファイルだけでなくリソースを常に閉じます。

実際に裏を覗きたい場合は、ほとんどのJava APIのソースが利用可能です。BufferedWriterは here です。

6
Jaimin Patel

コードは、書き込みを終了した後、ライターを閉じているようには見えません。 out.close()を(できればfinallyブロックに)追加すると、適切に動作するはずです。

5
Ian Roberts

bufferedWriterを閉じないで、finallyブロック内で閉じます

   finally {
    out.close();//this would resolve the issue
    }
5
PermGenError

bufferedWriterを閉じないで、finallyブロック内で閉じます

finally {
out.close();//this would resolve the issue
}

これは動作します。私は同じ問題に直面しており、これは私のために働いた..幸運:)

1
Harini

リソースを使い終わったら、リソース(ファイルだけでなく)を常に閉じてください。

 finally {
    out.close();//this would resolve the issue
    }

ファイルを閉じずにバッファをフラッシュしたい場合があります。これらの状況では、flush-methodを使用できます。

1
Harita M

BufferedWriterを使用しているため、必要に応じてバッファーをフラッシュすることもできます。

out.flush()

これにより、残りのバッファが実際のファイルに書き込まれます。また、close-methodはバッファーをフラッシュし、ファイルを閉じます。

out.close()

ファイルを閉じずにバッファをフラッシュしたい場合があります。これらの状況では、flush-methodを使用できます。

行の末尾に\ nを追加する代わりに、BuffredWriterのnewline-methodを使用することもできます。 Newline-methodはシステム固有の行区切り記号を使用するため、コードはさまざまなプラットフォームで動作します。

out.newLine()
0
niklasgerdt