33

ファイルからテキストを1行ずつ読み取り、新しいテキストを出力ファイルに書き込むJavaプログラムがあります。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行後、ファイルの終わりの数百行前に発生します。ブレークが発生する場所は、a1とaの間,です。1ただし、を変更すると42、新しいファイルに書き込まれる最後のものは、であるため、文字は重要ではないようです4。これは、その整数から2を切り取っています。ですから、読者や作家は、ある程度の量の書き込み/読み取りを行った後、ただ死にかけているに違いないようです。

私の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);
        }
    }
}
4

8 に答える 8

71

を閉じる必要があります。OutputStreamこれにより、残りのデータがフラッシュされます。

out.close();

のデフォルトのバッファサイズBufferedWriter8192文字で、数百行の未書き込みデータを簡単に保持するのに十分な大きさです。

于 2012-11-16T23:57:31.333 に答える
13

あなたはあなたでなければなりません 。IS-Aであるため、実装する必要があります。つまり、(強調が追加された)close()BufferedWriterclose()BufferedWriterWriterAutoCloseable

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

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

フラッシング(flush())の文書化されたセマンティクスは次のとおりです。

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

したがって、バッファリングされた出力をフラッシュする必要がありcloseます。close

BufferedWriter出力ファイルには、そのテキストの一部がバッファに格納されているため、書き込んだすべてのテキストが含まれているわけではありません。あなたBufferedWriterがそうするように言ったことがないので、決してそのバッファを空にせず、それをファイルに渡します。


AutoCloseableJava 7以降、などのリソースBufferedWriterが不要になったときに閉じるための最善の方法は、 try-with-resourcesとも呼ばれる自動リソース管理(ARM)を使用することです。

 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
 }

close()コードがライターを使用して「終了」したときに、メソッドの最後で呼び出すように誘惑されないでください(ここでの他の回答が示唆しているように) 。記述コードが例外をスローした場合、特にそれが。をスローした場合、これは機能しませんIOException

于 2015-01-06T14:04:44.570 に答える
7

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

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

考慮すべきいくつかの事柄:

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

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

本当に内部を覗き見したい場合は、JavaAPIのソースのほとんどが利用可能です。BufferedWriterはここにあります。

于 2016-02-29T09:58:08.750 に答える
5

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

于 2012-11-16T23:58:47.103 に答える
5

BufferedWriterを閉じます。finallyブロック内で閉じます。

   finally {
    out.close();//this would resolve the issue
    }
于 2012-11-16T23:58:56.883 に答える
1

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

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

ファイルを閉じずにバッファをフラッシュしたい場合があります。このような状況では、flushメソッドを使用できます。

于 2016-08-11T11:36:36.717 に答える
0

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

out.flush()

これにより、残りのバッファが実際のファイルに書き込まれます。Closeメソッドは、バッファをフラッシュしてファイルを閉じます。

out.close()

ファイルを閉じずにバッファをフラッシュしたい場合があります。このような状況では、flushメソッドを使用できます。

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

out.newLine()
于 2014-11-24T10:40:04.077 に答える
-1

ドキュメントによると、flush()メソッドを呼び出すことは無駄です。あなたが使用するつもりなら、FileWriterそれからflush()あなたを助けるでしょう。

基本的にこの場合、あなたはただ閉じる必要がありますBufferedWriter.close()。これにより、残りのデータがフラッシュされます。

finallyブロックを作成し、closeメソッドを内部に配置して、すべてのデータを見逃さずに配置できるようにします。

 finally {
    out.close();
    }
于 2020-07-04T12:30:21.640 に答える