我正在将Unix C应用程序移植到Windows。这个应用程序在打开时重命名文件,这在Unix上完全没问题,但显然它在Windows上不起作用。跟踪所有重命名以确保我关闭文件,然后重新打开并再次寻找将是痛苦的。
鉴于Windows资源管理器允许在使用时重命名文件,我想知道为什么我不能让它工作。我在C中尝试了rename和MoveFile,在C#中尝试了System.IO.File.Move。它在所有情况下都失败并出现“Permission denied”错误(具体而言,GetLastError()返回的错误是“进程无法访问该文件,因为它正被另一个进程使用”)
提示?
我还试图打开文件与_sopen共享。它也不起作用(相同的错误)。
感谢Stefan编写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 :(得分:15)
重命名要求使用FileShare.Delete共享打开相关文件。 如果缺少该共享标志,则无法在文件仍处于打开状态时重命名/移动该文件。
答案 1 :(得分:4)
这取决于文件的打开方式。如果使用锁打开文件,则无法写入或重命名。像Notepad ++这样的工具打开文件而不锁定它。如果您是打开并编辑它的人,您也可以这样做:
http://balajiramesh.wordpress.com/2008/07/16/using-streamreader-without-locking-the-file-in-c/
本文中的代码显示了如何将FileStream与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();
}