2011-08-22 95 views
12

我將一個Unix C應用程序移植到Windows。這個應用程序在打開時重命名文件,這在Unix上是完美的,但顯然它不適用於Windows。跟蹤所有的重命名,以確保我關閉該文件,然後重新打開並再次尋找將是痛苦的。以編程方式重命名Windows上的打開文件

鑑於Windows資源管理器允許在使用時重命名文件,我不知道爲什麼我無法使其工作。我已經在C中嘗試了renameMoveFile,並且在C#中使用了System.IO.File.Move。它在所有情況下都會出現「權限被拒絕」錯誤(具體來說,GetLastError()返回的錯誤是「進程無法訪問該文件,因爲它正在被另一進程使用」)

提示?

我也嘗試打開文件與_sopen共享。它也沒有工作(同樣的錯誤)。

C工作感謝斯特凡#代碼:

string orig_filename = "testrenamesharp-123456"; 
string dest_filename = "fancynewname.txt"; 
Byte[] info = new UTF8Encoding(true).GetBytes("This is to test the OpenWrite method."); 
var fs = new FileStream(orig_filename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete); 
fs.Write(info, 0, info.Length); 
File.Move(orig_filename, dest_filename); 
fs.Close(); 

工作C示例:

const char* filename = "testrename-XXXXXX"; 
const char* dest_filename = "fancynewname.txt"; 

/* The normal POSIX C functions lock the file */ 
/* int fd = open(filename, O_RDWR | O_CREAT, _S_IREAD | _S_IWRITE); */ /* Fails */ 
/* int fd = _sopen(filename, O_RDWR | O_CREAT, _SH_DENYNO, _S_IREAD | _S_IWRITE); */ /* Also fails */ 

/* We need to use WINAPI + _open_osfhandle to be able to use 
    file descriptors (instead of WINAPI handles) */ 
HANDLE hFile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY, NULL); 
if(INVALID_HANDLE_VALUE == hFile) { 
    ErrorExit(TEXT("CreateFile")); 
} 

int fd = _open_osfhandle((long int)hFile, _O_CREAT | _O_RDWR | _O_TEMPORARY); 
if(-1 == fd) { 
    perror("open"); 
} 

int resw = write(fd, buf, strlen(buf)); 
if(-1 == resw) { 
    perror("write"); 
} 

if(0 == access(dest_filename, F_OK)) { 
    perror("access"); 
} 

/* Now try to rename it - On Windows, this fails */ 
int resr = rename(filename, dest_filename); 
if(-1 == resr) { 
    perror("rename"); 
} 

int resc = close(fd); 
if(-1 == resc) { 
    perror("close"); 
} 
+0

您遇到了什麼樣的故障? – StevenV

+0

權限被拒絕。 – pgquiles

+2

Windows資源管理器允許在使用時重命名(鎖定)文件?從何時起? –

回答

12

重命名要求該問題的文件是用FileShare.Delete共享打開的。 如果共享標誌丟失,則在文件仍處於打開狀態時無法重命名/移動該文件。

+0

謝謝!這在C#中有效,現在我只需要計算出C中FileShare.Delete的等效內容: -/ – pgquiles

+1

請參閱http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85% 29.aspx特別是dwShareMode參數(FILE_SHARE_DELETE) – Joe

+0

@Joe:謝謝,我剛剛發現了這個並完成了測試。我編輯了C樣本。我也需要使用_open_osfhandle,因爲應用程序使用文件描述符。 – pgquiles

4

這取決於文件的打開方式。如果文件是用鎖打開的,你不能寫或重命名它。像記事本+ + +的工具打開文件,而不鎖定它。如果你是誰打開和編輯它的人,你也可以這樣做:

http://balajiramesh.wordpress.com/2008/07/16/using-streamreader-without-locking-the-file-in-c/

本文中的代碼展示瞭如何使用一個FileStream與文件共享選項:

using(FileStream fs = new FileStream(@」c:\test.txt」, FileMode.Open, FileAccess.Read,FileShare.ReadWrite)) 
{ 
    StreamReader sr = new StreamReader(fs); 
    txtContents.Text = sr.ReadToEnd(); 
    sr.Close(); 
} 
+0

這不起作用,請參閱我的C#示例 – pgquiles