BufferedWriter没有将所有内容写入其输出文件

时间:2012-11-16 23:55:55

标签: java file-io bufferedwriter

我有一个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行之后,但在文件结束之前有几百行。发生中断的地方是1,之间。但是,这些字符似乎并不重要,因为如果我将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);
        }
    }
}

9 个答案:

答案 0 :(得分:63)

您需要关闭OutputStream,这将清除剩余的数据:

out.close();

BufferedWriter的默认缓冲区大小为8192 characters,大小足以轻松容纳数百行未写入数据。

答案 1 :(得分:9)

必须 close()您的BufferedWriter。您必须close() BufferedWriter,因为它是IS-A Writer,因此实施AutoCloseable,这意味着(强调添加)它是

  

不再需要必须关闭的资源

有人说在致电BufferedWriter之前,您必须先为close()致电flush()。他们错了。 BufferedWriter.close()的文档指出它“关闭流,首先刷新”(强调添加)。

记录的刷新语义(flush())是

  

通过将任何缓冲的输出写入基础流

来刷新此流

因此,您必须closeclose将刷新任何缓冲的输出。

您的输出文件不包含您写入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
 }

答案 2 :(得分:6)

  

不再需要时必须关闭的资源。

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

需要考虑的一些事项:

  • BufferedWriter.close() 将缓冲区刷新到基础流,因此如果您忘记flush()并且没有关闭,则您的文件可能没有所有文字写信给它。
  • BufferedWriter.close()也关闭了包装的Writer。如果这是一个FileWriter,这将最终关闭FileOutputStream 并告诉操作系统您已完成写入该文件。
  • 垃圾收集器将自动调用close(),而不是BufferedWriter或包装的FileWriter,而是调用FileOuputStream。因此操作系统会很高兴,但您必须等待GC。
  • 但是,一旦不再需要,您总是希望释放操作系统资源。这适用于打开文件,数据库连接,打印队列......任何事情。相信我这个。
  • BufferedWriter.close()确实清除了内部字符缓冲区,因此即使BufferedWriter本身仍在范围内,内存也可用于垃圾收集。

因此,当您完成资源时,请务必关闭资源(而不仅仅是文件)。

如果您真的想要了解一下,大多数Java API的源代码都可用。 BufferedWriter是here

答案 3 :(得分:5)

在您完成写入后,您的代码似乎没有关闭作者。添加out.close()(最好在最后一个块中),它应该可以正常工作。

答案 4 :(得分:5)

你没有关闭你的BufferedWriter.close它在finally块

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

答案 5 :(得分:1)

你没有关闭你的BufferedWriter.close它在finally块

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

这很有效。我遇到了同样的问题,这对我有用......好运:)

答案 6 :(得分:1)

完成后,请务必关闭资源(而不仅仅是文件)。

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

在某些情况下,您可能需要在不关闭文件的情况下刷新缓冲区。在这些情况下,您可以使用flush-method。

答案 7 :(得分:0)

由于您正在使用BufferedWriter,您还可以在适当的时候刷新缓冲区:

out.flush()

这会将缓冲区的其余部分写入实际文件。 Close-method也会刷新缓冲区并关闭文件。

out.close()

在某些情况下,您可能需要在不关闭文件的情况下刷新缓冲区。在这些情况下,您可以使用flush-method。

您也可以使用BuffredWriter的换行方法,而不是将\ n添加到行尾。 Newline方法使用系统特定的行分隔符,因此您的代码可以在不同的平台上运行。

out.newLine()

答案 8 :(得分:0)

根据文档,调用flush()方法是没有用的。如果您打算使用FileWriter,那么flush()会为您提供帮助。

基本上,在这种情况下,您只需要关闭BufferedWriter.close()。这将刷新您的其余数据。

创建finally块并将close方法放入其中,以便它将所有数据放入而不会丢失。

 finally {
    out.close();
    }