我看到标准C无法告诉文件是否已经在另一个进程中打开。 所以答案应该包含每个平台的几个例子。 尽pipe我需要检查Visual C ++ / Windows。
除非另一个进程明确禁止访问文件,否则没有办法。 在MSVC中,您可以使用_fsopen()
来指定_SH_DENYRD
作为shflag参数。 关心一个文件是否被打开,而不是被锁定的概念,在多任务操作系统上存在严重缺陷。 它可能会打开一微秒之后,你会发现它不是。 这也是Windows没有IsFileLocked()函数的原因。
如果您需要对文件进行同步访问,则需要添加一个已命名的互斥锁,使用CreateMutex()。
Windows:尝试以独占模式打开文件。 如果有效,没有其他人打开文件,将无法打开文件
HANDLE fh; fh = CreateFile(filename, GENERIC_READ, 0 /* no sharing! exclusive */, NULL, OPEN_EXISTING, 0, NULL); if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE)) { // the only open file to filename should be fh. // do something CloseHande(fh); }
MS说:dwShareMode
一个对象的共享模式,可以是读,写,都可以,全部是这些,或者没有(参考下表)。
如果此参数为零且CreateFile成功,则该对象将无法共享,并且在关闭句柄之前无法再次打开该对象。
您无法请求与在打开的句柄中指定的访问模式冲突的共享模式,因为这会导致以下共享冲突:ERROR_SHARING_VIOLATION。
http://msdn.microsoft.com/en-us/library/windows/desktop/aa363858%28v=vs.85%29.aspx
扩展名:如何删除一个(不是只读的)文件系统,没有人可以读/写?
访问权限FILE_READ_ATTRIBUTES,而不是删除。 DELETE可能会导致smb共享(到MS Windows服务器)的问题 – CreateFile将留下一个仍然打开FileHandle /设备/ Mup:xxx文件名 – 为什么永远和这个Mup是什么。 访问权限不会发生FILE_READ_ATTRIBUTES使用FILE_FLAG_OPEN_REPARSE_POINT删除文件名。 否则,你将删除一个符号链接的目标 – 这通常不是你想要的
HANDLE fh; fh = CreateFile(filename, FILE_READ_ATTRIBUTES, FILE_SHARE_DELETE /* no RW sharing! */, NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_DELETE_ON_CLOSE, NULL); if ((fh != NULL) && (fh != INVALID_HANDLE_VALUE)) { DeleteFile(filename); /* looks stupid? * but FILE_FLAG_DELETE_ON_CLOSE will not work on some smb shares (eg samba)! * FILE_SHARE_DELETE should allow this DeleteFile() and so the problem could be solved by additional DeleteFile() */ CloseHande(fh); /* a file, which no one has currently opened for RW is delete NOW */ }
如何处理打开的文件? 如果该文件已打开并允许您取消链接,则会在后续打开的文件中留下一个文件,导致ACCESS_DENIED。 如果你有一个temoprary文件夹,比重新命名(filename,tempdir / filename.delete)和删除tempdir / filename.delete可能是一个好主意。
对于Windows,此代码也适用于:
boolean isClosed(File f) { return f.renameTo(f); }
打开的文件不能重命名,并重命名为相同的名称不会导致另一个错误。 所以,如果重命名成功,没有真正做过什么,你知道文件没有打开。
获取open_files信息是困难的,就像扯扯牙齿一样,如果你没有立即需要它,你不应该为每个平台要求“每个平台的几个例子”。 当然只是我的意见。
Linux和许多Unix系统都有一个名为lsof
的系统工具,它可以找到打开的文件句柄和东西。 这样做的方式是访问/dev/kmem
,它是一个包含“实时”内核内存副本的伪文件,即操作系统内核的工作存储器。 那里有开放文件的表格,内存结构是开放源代码的,有文件记录的,所以只需要大量的工作就可以进入,找到信息并为用户格式化。
另一方面,Windows深层内存的文档实际上是不存在的,我不知道数据结构是暴露在外的。 我不是Windows专家,但除非Windows API明确提供这种信息,否则可能根本不可用。
Mark Russinovich的SysInternals实用程序可能正在使用任何可用的程序; 首先想到的是FileMon。 看这些可能会给你一些线索。 更新:我刚刚被告知SysInternals Handles.exe更接近你想要的。
如果你能弄明白这一点,好的; 否则,您可能会对抓取文件打开/关闭操作感兴趣:Windows API提供了大量所谓的Hooks: http : //msdn.microsoft.com/zh-cn/library/ms997537.aspx 。 挂钩允许您在系统发生某些事情时请求通知。 我相信有一个会告诉你,当一个系统的程序打开一个文件。 所以你可以使你自己的文件列表打开你正在听你的挂钩的时间。 我不知道,但我怀疑这可能是FileMon做的。
包括钩子函数在内的Windows API可以从C中访问。系统范围的钩子将要求你创建一个DLL来和你的程序一起加载。
希望这些提示可以帮助你开始。
任何这样的检查都是天生的。 另一个进程总是可以在您执行检查的地方和您访问文件的地方之间打开文件。
到目前为止的答案应该告诉你,找出你所要求的信息是棘手的,不可移植的,并且通常本质上是不可靠的。 所以,从我的角度来看,真正的答案是不这样做 。 试着找到一种思考自己真正的问题的方法,这样就不会出现这个问题。
这不可能是那个硬汉。
做这个:
try{ File fileout = new File(path + ".xls"); FileOutPutStream out = new FileOutPutStream(fileout); } catch(FileNotFoundException e1){ // if a MS Windows process is already using the file, this exception will be thrown } catch(Exception e){ }