2011-08-22 14 views
12

Sto eseguendo il porting di un'applicazione Unix C su Windows. Questa applicazione rinomina i file mentre sono aperti, il che è perfetto per Unix ma a quanto pare non funziona su Windows. Tracciare tutti i nomi per assicurarsi che chiudo il file, quindi riaprire e cercare di nuovo sarebbe doloroso.Rinomina a livello di codice del file aperto su Windows

Dato che Windows Explorer consente di rinominare un file mentre è in uso, mi chiedo perché non riesco a farlo funzionare. Ho provato con rename e MoveFile in C e System.IO.File.Move in C#. Non riesce in tutti i casi con un errore "Autorizzazione negata" (in particolare, l'errore restituito da GetLastError() è "Il processo non può accedere al file perché viene utilizzato da un altro processo")

Suggerimenti?

Ho anche provato ad aprire il file per la condivisione con _sopen. Non ha funzionato neanche (lo stesso errore).

di lavoro di codice C# grazie a 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(); 

di lavoro C di esempio:

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

che tipo di guasti stai riscontrando? – StevenV

+0

Autorizzazione negata. – pgquiles

+2

Esplora risorse consente di rinominare un file (bloccato) mentre è in uso? Da quando? –

risposta

12

ridenominazione richiede che il file in questione è stato aperto con la condivisione FileShare.Delete. Se manca questo flag di condivisione, non è possibile rinominare/spostare il file mentre è ancora aperto.

+0

Grazie! Funziona in C#, ora ho solo bisogno di capire l'equivalente di FileShare.Delete in C: -/ – pgquiles

+1

Vedere http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85% 29.aspx in particolare il parametro dwShareMode (FILE_SHARE_DELETE) – Joe

+0

@Joe: Grazie, l'avevo appena scoperto e ho terminato i test. Ho modificato l'esempio C. Avevo bisogno di usare anche _open_osfhandle perché l'applicazione utilizza i descrittori di file. – pgquiles

4

Dipende da come il file è stato aperto. Se un file viene aperto con il blocco, non puoi scriverlo o rinominarlo. Strumenti come Notepad ++ aprono i file senza bloccarli. Se si è l'uno che si apre e si modifica, si può fare anche questo:

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

Il codice in questo articolo mostra come utilizzare un FileStream con opzioni 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

Che non funziona, vedere il mio esempio C# – pgquiles

Problemi correlati