据我所知,.NET FileStream的Flush方法只将当前缓冲区写入磁盘,但依赖于Windows的磁盘驱动程序和硬盘固件,这并不能保证数据实际上是物理写入磁盘的.
是否有.NET或Win32方法可以给我这个保证?因此,如果在调用此方法后一纳秒之后出现断电,我仍然可以确定一切正常吗?
我正在使用FileSystemWatcher监视文件夹,如下所示:
watcher = new FileSystemWatcher(folder);
watcher.NotifyFilter = NotifyFilters.Size;
watcher.Changed += changedCallback;
Run Code Online (Sandbox Code Playgroud)
当我在该文件夹中的记事本中打开一个新文件并保存时,我会收到通知.如果我继续写作然后保存,我会收到通知.如果我保存它关闭文件,我会收到通知.正是我想要的.
但是,事实证明,如果我在该文件夹中创建一个文件并将其共享模式设置为FileShare.Read,然后我写入它,则在文件关闭之前我不会收到任何通知.另一种解决方法是打开文件(例如在记事本中),这显然会导致其状态更新,然后我的监控应用程序会收到通知.另一种解决方法是我可以在Windows资源管理器中执行刷新,这再次导致文件状态更新.
有趣的是,如果我在进行更改时查看Windows资源管理器,我会注意到:
因此,我的监控应用程序似乎与Windows资源管理器共享相同的行为.我正在考虑运行一个只扫描文件夹中文件的线程,但我想知道在这种情况下是否还有更优雅的事情要做.
顺便说一下,我正在使用Win7,我不确定这个问题是否也会在其他Windows版本上发生.
谢谢!
编辑:在C++中使用ReadDirectoryChanges得到了相同的结果.实现我之前谈到的线程并没有帮助.我想知道Windows资源管理器中的F5究竟是做什么的,因为它确实会导致报告更改.
我正在尝试确定最坏情况下的磁盘速度,所以我编写了以下函数.
static public decimal MBytesPerSec(string volume)
{
string filename = volume + "\\writetest.tmp";
if (System.IO.File.Exists(filename))
System.IO.File.Delete(filename);
System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
char[] data = new char[64000];
Stopwatch watch = new Stopwatch();
watch.Start();
int i = 0;
for (; i < 1000; i++)
{
file.Write(data);
if (watch.ElapsedMilliseconds > 2000)
{
break;
}
}
watch.Stop();
file.Close();
System.IO.File.Delete(volume + "\\test.txt");
decimal mbytessec = (i * 64 / watch.ElapsedMilliseconds);
return mbytessec;
}
Run Code Online (Sandbox Code Playgroud)
该函数工作正常,但写入缓存,因此速度不是最坏的情况.
在WIN32 C++中,我只需使用选项创建文件FILE_FLAG_NO_BUFFERING,FILE_FLAG_WRITE_THROUGH然后确保遵循非缓存写入规则(以扇区大小偏移写入文件,最少写入4k)
我们有一个系统,客户端发出HTTP GET请求,系统对后端进行一些处理,压缩结果,然后将其发送给客户端.由于处理可能需要一些时间,我们将其作为ZipOutputStream包装发送response.getOutputStream().
但是,当我们在第一个中有非常少量的数据ZipEntry,而第二个条目需要很长时间时,客户端使用的浏览器会超时.我们已经尝试刷新流缓冲区,但是在向流写入至少1000个字节之前,似乎没有响应发送到浏览器.奇怪的是,一旦发送了前1000个字节,后续的刷新似乎工作正常.
我尝试将代码拆解为裸露的示例:
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
try {
ZipOutputStream _zos = new ZipOutputStream( response.getOutputStream());
ZipEntry _ze = null;
long startTime = System.currentTimeMillis();
long _lByteCount = 0;
response.setContentType("application/zip");
while (_lByteCount < 2000) {
_ze = new ZipEntry("foo");
_zos.putNextEntry( _ze );
//writes 100 bytes and then waits 10 seconds
_lByteCount += StreamWriter.write(
new ByteArrayInputStream(DataGenerator.getOutput().toByteArray()),
_zos );
System.out.println("Zip: " + _lByteCount + " Time: " + ((System.currentTimeMillis() - startTime) …Run Code Online (Sandbox Code Playgroud)