gol*_*enk 29 java file-io bufferedwriter
我有一个Java程序,它从文件中逐行读取一些文本,并将新文本写入输出文件.但是BufferedWriter,在程序完成后,我写入的所有文本都不会出现在输出文件中.这是为什么?
详细信息:程序采用CSV文本文档并将其转换为SQL命令以将数据插入表中.文本文件超过10000行,类似于以下内容:
2007,10,9,1,1,1006134,19423882
Run Code Online (Sandbox Code Playgroud)
该程序似乎工作正常,除了它只是在文件中随机停止创建一个新的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
Run Code Online (Sandbox Code Playgroud)
这在大约10000行之后发生,但在文件结束之前有几百行.中断发生的地方是a 1和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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
Rei*_*eus 64
您需要关闭OutputStream将刷新剩余数据的内容:
out.close();
Run Code Online (Sandbox Code Playgroud)
默认缓冲区大小BufferedWriter为8192个字符,大到足以轻松容纳数百个不成文的行的数据.
Rae*_*ald 10
你必须 close()你的BufferedWriter.你必须close()你的BufferedWriter,因为它是-A Writer,因此工具AutoCloseable,这意味着(强调)是
在不再需要时必须关闭的资源.
有人说,你必须先调用flush()您BufferedWriter之前调用close().他们错了.它的文档BufferedWriter.close()"关闭流,首先刷新它 "(强调添加).
flushing(flush())的文档语义是
通过将任何缓冲的输出写入基础流来刷新此流
所以,你必须close,close并将刷新任何缓冲的输出.
您的输出文件不包括您写入的所有文本,BufferedWriter因为它将一些文本存储在缓冲区中.该BufferedWriter从来没有清空该缓冲区,将其通过该文件,因为你从来没有告诉它这样做.
从Java 7开始,确保AutoCloseable资源(如a)的最佳方法BufferedWriter是在不再需要时关闭,使用自动资源管理(ARM),也称为try-with-resources:
try (BufferedWriter out = new BufferedWriter(new FileWriter(file))) {
// writes to out here
} catch (IOException ex) {
// handle ex
}
Run Code Online (Sandbox Code Playgroud)
您还必须close你BufferedReader当它是不再需要的,所以你应该嵌套的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
}
Run Code Online (Sandbox Code Playgroud)
在不再需要时必须关闭的资源.
finally {
out.close();//this would resolve the issue
}
Run Code Online (Sandbox Code Playgroud)
有些事情需要考虑:
BufferedWriter.close() 将缓冲区刷新到基础流,因此如果您忘记flush()并且不关闭,则您的文件可能没有您写入的所有文本.BufferedWriter.close()也关闭了包装的作家.当这是一个FileWriter时,这将最终关闭FileOutputStream并告诉操作系统您已完成写入该文件.close(),而不是在BufferedWriter或包装的FileWriter上,而是在FileOuputStream上.因此操作系统会很高兴,但您必须等待GC.BufferedWriter.close() 确实清除内部字符缓冲区,这样即使BufferedWriter本身仍在范围内,内存也可用于垃圾收集. 因此,当您完成它们时,请始终关闭您的资源(而不仅仅是文件).
如果你真的想要了解一下,大多数Java API的源代码都是可用的.BufferedWriter就在这里.
你将你的BufferedWriter.close关闭在finally块中
finally {
out.close();//this would resolve the issue
}
Run Code Online (Sandbox Code Playgroud)