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

java file-io bufferedwriter

40783 观看

8回复

3879 作者的声誉

我有一个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 1和a 之间,。但是,这些字符似乎并不重要,因为如果将更1改为a,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);
        }
    }
}
作者: golmschenk 的来源 发布者: 2012 年 11 月 16 日

回应 (8)


63

144603 作者的声誉

决定

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

out.close();

默认缓冲区大小BufferedWriter8192个字符,大到足以轻松容纳数百个不成文的行的数据。

作者: Reimeus 发布者: 16.11.2012 11:57

5

107948 作者的声誉

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

作者: Ian Roberts 发布者: 16.11.2012 11:58

5

40952 作者的声誉

您关闭BufferedWriter.close在finally块中

   finally {
    out.close();//this would resolve the issue
    }
作者: PermGenError 发布者: 16.11.2012 11:58

1

11 作者的声誉

您关闭BufferedWriter.close在finally块中

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

这可行。我也遇到过同样的问题,这对我有用。.祝你好运:)

作者: Harini 发布者: 02.04.2014 01:45

0

79 作者的声誉

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

out.flush()

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

out.close()

在某些情况下,您想刷新缓冲区而不关闭文件。在这些情况下,您可以使用冲洗方法。

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

out.newLine()
作者: niklasgerdt 发布者: 24.11.2014 10:40

9

28991 作者的声誉

必须 close()你的BufferedWriter。你必须close()你的BufferedWriter,因为它是-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
 }

您还必须closeBufferedReader当它是不再需要的,所以你应该嵌套的try-与资源块:

 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
 }
作者: Raedwald 发布者: 06.01.2015 02:04

6

3485 作者的声誉

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

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

要考虑的一些事情:

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

因此,使用完资源后,请务必关闭资源(不仅仅是文件)。

如果您真的想偷看之下,可以使用大多数Java API的资源。BufferedWriter在这里

作者: Jaimin Patel 发布者: 29.02.2016 09:58

1

119 作者的声誉

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

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

在某些情况下,您想刷新缓冲区而不关闭文件。在这些情况下,您可以使用冲洗方法。

作者: Harita M 发布者: 11.08.2016 11:36
32x32