2009-12-23 191 views
8

我看到标准C无法判断文件是否已经在另一个进程中打开。所以答案应该包含每个平台的几个例子。尽管我需要检查Visual C++/Windows。如何检查一个文件是否已被C中的另一个进程打开?

+0

为什么你想知道一个文件是否被另一个进程打开?另外,您是否想要确定该文件是通过特定(即已知)进程打开还是仅由其他进程打开? – 2009-12-23 11:29:06

+0

就是如果另一个进程已经同时访问。如果该文件正在使用中,则在继续时可能会损坏某些内容。 – winlin 2009-12-23 11:43:13

+0

我对“哪个”进程访问信息不感兴趣。 这个问题在这里,因为没有人似乎在其他平台上回答这个问题,但它可能有必要知道这一点。所以请保持简短,并且不要说“重新思考”这个问题。想想浏览器,就好像在删除文件之前一样,它会检查是否有其他进程正在访问它。 – winlin 2009-12-23 11:45:10

回答

7

除非另一个进程明确禁止访问文件,否则无法判断。在MSVC中,您应该使用_fsopen(),为shflag参数指定_SH_DENYRD。感兴趣的是,打开一个文件是否被锁定,这个概念在多任务操作系统上存在严重缺陷。它可能会在你发现它不是一微秒后打开。这也是Windows没有IsFileLocked()函数的原因。

如果您需要对文件进行同步访问,则需要添加一个带有名称的互斥体,使用CreateMutex()。

+0

谢谢。对于Windows这个工作,真的帮助我的问题。其余的是为其他人寻求其他平台的答案可能。 – winlin 2009-12-23 11:46:49

1

任何此类检查本质上都会很激烈。另一个进程可以始终在您执行检查的位置与您访问文件的位置之间打开文件。

3

获取open_files信息很困难,就像拉动牙齿一样,如果你没有立即需要它,你就不应该为每个平台要求“几个平台的例子”。当然只是我的意见。

Linux和许多Unix系统都有一个名为lsof的系统实用程序,它查找打开的文件句柄和内容。这样做的方式是访问/dev/kmem,这是一个包含“实时”内核内存副本的伪文件,即操作系统内核的工作存储。在那里有开放文件的表格,内存结构是开放源代码的,并且有文档记录,所以这只是lsof进入该网站的大量繁琐工作,需要为用户找到信息并进行格式化。另一方面,Windows深层内存的文档实际上并不存在,我不知道数据结构在某种程度上暴露于外部。我不是Windows专家,但除非Windows API明确提供此类信息,否则它可能根本无法使用。

Mark Russinovich的SysInternals公用程序可能正在使用任何程序;首先想到的是FileMon。看着这些可能会给你一些线索。 更新:我刚刚被告知,SysInternals Handles.exe更接近你想要的。

如果你设法弄清楚,好;否则,您可能会对抓取文件打开/关闭操作感兴趣:Windows API提供了大量的所谓的钩子:http://msdn.microsoft.com/en-us/library/ms997537.aspx。挂钩允许您在系统发生某些事情时请求通知。我相信有一个会告诉你什么时候系统范围–打开一个文件。因此,您可以制作自己的文件列表,以便在您收听挂钩期间打开文件。我不确定,但我怀疑这可能是FileMon所做的。

可以从C访问Windows API,包括挂钩函数。系统范围挂钩将需要创建一个DLL,以便与您的程序一起加载。

希望这些提示可以帮助您开始。

+1

在Windows中可以这样做。例如,Sysinternals handle.exe工具就是这样做的。 http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx – 2009-12-23 11:29:33

+0

+1,谢谢!我刚刚更新了我的答案以反映这一点。 – 2009-12-23 12:12:45

0

到目前为止的答案应该告诉你,找出你要求的信息是棘手的,不可移植的,并且通常本质上不可靠。所以,从我的角度来看,真正的答案是不要那样做。试着找到一种思考自己真正的问题的方法,这样就不会出现这个问题。

6

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。 DELETE可能会导致smb共享(对MS Windows服务器)出现问题 - CreateFile将以一个仍然打开的FileHandle/Device/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 (e.g. 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可能是个好主意。

0

这不可能是那个硬汉。

做到这一点:

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){ 

} 
+1

呃,好,但不是C ...? – 2017-04-19 13:35:43

+0

真的,大声笑哎呀抱歉 – 2017-04-19 18:40:03

4

对于Windows,此代码的工作也:

boolean isClosed(File f) { return f.renameTo(f); } 

打开的文件不能被重命名,并且重命名,以相同的名称不会导致另一个错误。所以如果重命名成功,没有真正做过什么,那么你知道该文件没有打开。

+0

这对我很有用,而且实现起来非常简单!这可能是Java而不是C,这也许就是为什么你被低估了。我发现这个答案非常有帮助,谢谢。 – Rich 2015-11-25 17:35:25

+0

您使用哪个库进行重命名操作?,因为如果我尝试用'std :: rename'重命名该文件,Windows允许重命名该文件,尽管它已打开。 – 2016-05-03 19:19:04

相关问题