2009-12-23 187 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

相關問題