在读Lucene的源码过程中,发现FSDirectory类中有一个文件信息同步的方法,对其中的一行代码file.getFD().sync();不是很清楚(这也可见自己的基础有多么的差)。经过一番检索,终于明白了其大意。
protected void fsync(String name) throws IOException {
File fullFile = new File(directory, name);
boolean success = false;
int retryCount = 0;
IOException exc = null;
while (!success && retryCount < 5) {
retryCount++;
RandomAccessFile file = null;
try {
try {
file = new RandomAccessFile(fullFile, "rw");
file.getFD().sync();//强制所有系统缓冲区与基础设备同步
success = true;
} finally {
if (file != null)
file.close();
}
} catch (IOException ioe) {
if (exc == null)
exc = ioe;
try {
// Pause 5 msec
Thread.sleep(5);
} catch (InterruptedException ie) {
throw new ThreadInterruptedException(ie);
}
}
}
if (!success)
// Throw original exception
throw exc;
}
}
File fullFile = new File(directory, name);
boolean success = false;
int retryCount = 0;
IOException exc = null;
while (!success && retryCount < 5) {
retryCount++;
RandomAccessFile file = null;
try {
try {
file = new RandomAccessFile(fullFile, "rw");
file.getFD().sync();//强制所有系统缓冲区与基础设备同步
success = true;
} finally {
if (file != null)
file.close();
}
} catch (IOException ioe) {
if (exc == null)
exc = ioe;
try {
// Pause 5 msec
Thread.sleep(5);
} catch (InterruptedException ie) {
throw new ThreadInterruptedException(ie);
}
}
}
if (!success)
// Throw original exception
throw exc;
}
}
FileDescriptor文件描述符类的实例用作与基础机器有关的某种结构的不透明句柄,该结构表示开放文件、开放套接字或者字节的另一个源或接收者。文件描述符的主要实际用途是创建一个包含该结构的 FileInputStream 或 FileOutputStream。 应用程序不应创建自己的文件描述符。
大部分人都认为flush后,其他用户应该立即可见。但是在一些极端的情况下也需调用后还是无法看见以写入的数据。
flush
刷新此输出流并强制写出所有缓冲的输出字节。flush 的常规协定是:如果此输出流的实现已经缓冲了以前写入的任何字节,则调用此方法指示应将这些字节立即写入它们预期的目标。
如果此流的预期目标是由基础操作系统提供的一个抽象(如一个文件),则刷新此流只能保证将以前写入到流的字节传递给操作系统进行写入,但不保证能将这些字节实际写入到物理设备(如磁盘驱动器)。
OutputStream 的 flush 方法不执行任何操作。为什么会这样? 原因是,这个缓冲我们java自己实现的。 flush保证的是内部的缓冲写入到系统中。但是系统中文件也可能有缓冲,所以并不一定flush后立即可见。
那么如何解决这个问题?在文件流或数据流中均可以看见getFD()这个方法, 它返回的是与此流有关的文件描述符。
所以调用文件描述符的sync的方法即可让实际文件强制同步了。JDK中描述如下:
sync
强制所有系统缓冲区与基础设备同步。该方法在此 FileDescriptor 的所有修改数据和属性都写入相关设备后返回。特别是,如果此 FileDescriptor 引用物理存储介质,比如文件系统中的文件,则一直要等到将与此 FileDesecriptor 有关的缓冲区的所有内存中修改副本写入物理介质中,sync 方法才会返回。 sync 方法由要求物理存储(比例文件)处于某种已知状态下的代码使用。例如,提供简单事务处理设施的类可以使用 sync 来确保某个文件所有由给定事务造成的更改都记录在存储介质上。 sync 只影响此 FileDescriptor 的缓冲区下游。如果正通过应用程序(例如,通过一个 BufferedOutputStream 对象)实现内存缓冲,那么必须在数据受 sync 影响之前将这些缓冲区刷新,并转到 FileDescriptor 中(例如,通过调用 OutputStream.flush)。来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/28624388/viewspace-763524/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/28624388/viewspace-763524/