今天,当我正在编写某种servlet,它将一些信息写入硬盘上的某个文件时,我使用以下代码来执行写入操作
File f=new File("c:/users/dell/desktop/ja/MyLOgs.txt");
PrintWriter out=new PrintWriter(new FileWriter(f,true));
out.println("the name of the user is "+name+"n");
out.println("the email of the user is "+ email+"n");
out.close(); //**my question is about this statement**
当我不使用该语句时,servlet编译得很好,但它没有向文件写入任何内容,但是当我包含它时,则写入操作成功执行。我的问题是:
- 为什么数据没有被写入文件时,我不包括该语句(甚至我的servlet正在编译没有任何错误)?
- 流的关闭操作在多大程度上是可观的?
调用close()
将刷新所有数据。您在没有启用自动刷新(其中一个构造函数的第二个参数)的情况下构造了PrintWriter
,这意味着您必须手动调用flush()
,而close()
为您完成了该操作。
关闭还释放了打开文件所使用的任何系统资源。虽然虚拟机和操作系统最终会关闭该文件,但最好在完成后关闭它,以节省计算机内存。
您也可以将close()
放在finally
块中,以确保总是被调用。如:
PrintWriter out = null;
try {
File f = new File("c:/users/dell/desktop/ja/MyLOgs.txt");
out = new PrintWriter(new FileWriter(f,true));
out.println("the name of the user is "+name+"n");
out.println("the email of the user is "+ email+"n");
} finally {
out.close();
}
看到:PrintWriter
Sanchit还提出了一个很好的观点,让Java 7 VM在你不需要流的时候自动关闭它们。
当您close
a PrintWriter
时,它会将其所有数据刷新到您希望数据去的任何地方。它不会自动执行此操作,因为如果每次写入时都执行此操作,将会非常低效,因为写入不是一个简单的过程。
您可以使用flush();
实现相同的效果,但您应该始终关闭流-参见这里:http://www.javapractices.com/topic/TopicAction.do?Id=8和这里:http://docs.oracle.com/javase/tutorial/jndi/ldap/close.html。当你用完流的时候,总是调用close();
。此外,为了确保无论异常如何总是关闭,您可以这样做:
try {
//do stuff
} finally {
outputStream.close():
}
这是因为PrintWriter
缓冲您的数据,以便不为每个写操作重复进行I/O操作(这是非常昂贵的)。当您调用close()
时,缓冲区将刷新到文件中。您还可以调用flush()
来强制写入数据而不关闭流。
流在关闭前自动刷新它们的数据。因此,您可以使用out.flush();
每隔一段时间手动刷新数据,或者您可以在完成后关闭流。当程序结束时,流关闭,您的数据被刷新,这就是为什么大多数时候人们不关闭他们的流!
使用Java 7,你可以像下面这样做,它会自动关闭你的流按照你打开它们的顺序。
public static void main(String[] args) {
String name = "";
String email = "";
File f = new File("c:/users/dell/desktop/ja/MyLOgs.txt");
try (FileWriter fw = new FileWriter(f, true); PrintWriter out = new PrintWriter(fw);) {
out.println("the name of the user is " + name + "n");
out.println("the email of the user is " + email + "n");
} catch (IOException e) {
e.printStackTrace();
}
}
PrintWriter
对要写入的数据进行缓冲,直到缓冲区满了才写入磁盘。调用close()
将确保所有剩余的数据都被刷新,并关闭OutputStream
。
close()
语句一般出现在finally
块中。
当我没有包含该语句时,为什么数据没有被写入文件?
当进程终止时,非托管资源将被释放。对于InputStreams,这很好。对于OutputStreams,您可能会丢失缓冲的数据,因此您至少应该在退出程序之前刷新流。