2011-08-22 32 views
12

Tôi đang chuyển ứng dụng Unix C sang Windows. Ứng dụng này đổi tên các tập tin trong khi chúng được mở, đó là hoàn toàn tốt đẹp trên Unix nhưng dường như nó không hoạt động trên Windows. Truy tìm tất cả các tên gọi để chắc chắn rằng tôi đóng tập tin, sau đó mở lại và tìm kiếm lại sẽ rất đau đớn.Lập trình đổi tên tệp mở trên Windows

Cho rằng Windows Explorer cho phép đổi tên tệp trong khi đang sử dụng, tôi tự hỏi tại sao tôi không thể làm việc này. Tôi đã thử với renameMoveFile trong C và System.IO.File.Move trong C#. Nó không thành công trong tất cả các trường hợp với lỗi "Quyền bị từ chối" (cụ thể, lỗi được trả về bởi GetLastError() là "Quá trình không thể truy cập tệp vì nó đang được sử dụng bởi một tiến trình khác")

Mẹo?

Tôi cũng đã cố mở tệp để chia sẻ với _sopen. Nó không hoạt động (cùng một lỗi).

Working C# code nhờ Stefan:

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(); 

Working C mẫu:

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

bạn đang gặp phải những sự cố gì? – StevenV

+0

Quyền bị từ chối. – pgquiles

+2

Windows explorer cho phép đổi tên tệp (bị khóa) trong khi đang sử dụng? Kể từ khi? –

Trả lời

12

đổi tên đòi hỏi tệp được đề cập đã được mở với chia sẻ FileShare.Delete. Nếu cờ chia sẻ đó bị thiếu, bạn không thể đổi tên/di chuyển tệp trong khi vẫn mở.

+0

Cảm ơn bạn! Điều đó làm việc trong C#, bây giờ tôi chỉ cần tìm ra tương đương với FileShare.Delete trong C: -/ – pgquiles

+1

Xem http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85% 29.aspx cụ thể tham số dwShareMode (FILE_SHARE_DELETE) – Joe

+0

@Joe: Cảm ơn bạn, tôi vừa tìm thấy về điều đó và đã hoàn thành kiểm tra. Tôi đã chỉnh sửa mẫu C. Tôi cũng cần sử dụng _open_osfhandle vì ứng dụng sử dụng các trình mô tả. – pgquiles

4

Nó phụ thuộc vào cách các tập tin đã được mở ra. Nếu một tệp được mở bằng khóa, bạn không thể viết hoặc đổi tên nó. Các công cụ như Notepad ++ mở tập tin mà không cần khóa nó. Nếu bạn là một trong những người mở ra và chỉnh sửa nó, bạn có thể làm điều đó quá:

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

Mã trong bài viết cho thấy làm thế nào để sử dụng một FileStream với các tùy chọn FileShare:

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

Điều đó không có tác dụng, hãy xem mẫu C# – pgquiles

Các vấn đề liên quan