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

2022-09-01 07:09:22

我有一个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行之后,但在文件结束前几百行之后。中断发生的位置是在 a 和 .但是,字符似乎并不重要,因为如果我将 更改为 a,则写入新文件的最后一件事是 ,这会从该整数中切断 2。因此,读者或作家似乎在写完/读完一定数量后一定只是死了。1,1424

我的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);
        }
    }
}

答案 1

您需要关闭将刷新其余数据:OutputStream

out.close();

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


答案 2

您必须关闭() 您的 .你必须你的,因为它是一个作家,因此实现自动关闭,这意味着(着重号是后加的)它是BufferedWriterclose()BufferedWriter

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

有人说,在调用 之前,您必须先调用 flush() 作为您的。他们错了。文档指出它“关闭流,首先刷新它”(着重号是后加的)。BufferedWriterclose()BufferedWriter.close()

flushing (flush()) 的记录语义是

通过将任何缓冲输出写入基础流来刷新此流

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

输出文件不包括您写入的所有文本,因为它将部分文本存储在缓冲区中。从未清空该缓冲区,将其传递到文件,因为您从未告诉它这样做。BufferedWriterBufferedWriter


从 Java 7 开始,确保资源(如 a)在不再需要时关闭的最佳方法是使用自动资源管理 (ARM),也称为 try-with-resourcesAutoCloseableBufferedWriter

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

当不再需要它时,您也必须这样做,因此您应该具有嵌套的试用资源块:closeBufferedReader

 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