2011-08-22 5 views
12

Estoy portando una aplicación Unix C a Windows. Esta aplicación cambia el nombre de los archivos mientras están abiertos, lo cual está perfectamente bien en Unix, pero aparentemente no funciona en Windows. Rastrear todos los renombrados para asegurarse de cerrar el archivo, volver a abrir y buscar nuevamente sería doloroso.Renombre de forma programable el archivo abierto en Windows

Dado que Windows Explorer permite cambiar el nombre de un archivo mientras está en uso, me pregunto por qué no puedo hacer que esto funcione. He intentado con rename y MoveFile en C, y System.IO.File.Move en C#. Falla en todos los casos con un error "Permiso denegado" (específicamente, el error devuelto por GetLastError() es "El proceso no puede acceder al archivo porque lo está utilizando otro proceso")

¿Sugerencias?

También intenté abrir el archivo para compartir con _sopen. Tampoco funcionó (el mismo error).

de trabajo de código C# gracias 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(); 

de trabajo C de la muestra:

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

¿qué tipo de fallas estás experimentando? – StevenV

+0

Permiso denegado. – pgquiles

+2

Windows Explorer permite cambiar el nombre de un archivo (bloqueado) mientras está en uso? ¿Desde cuando? –

Respuesta

12

cambio de nombre requiere que el archivo en cuestión se abrió con FileShare.Delete compartiendo. Si falta ese indicador de compartir, no puede cambiar el nombre/mover el archivo mientras aún está abierto.

+0

¡Gracias! Eso funciona en C#, ahora solo necesito descubrir el equivalente de FileShare. Eliminar en C: -/ – pgquiles

+1

Ver http://msdn.microsoft.com/en-us/library/aa363858%28v=vs.85% 29.aspx específicamente el parámetro dwShareMode (FILE_SHARE_DELETE) – Joe

+0

@Joe: Gracias, acabo de encontrarlo y terminé las pruebas. He editado la muestra C Necesitaba usar _open_osfhandle también porque la aplicación usa los descriptores de archivo. – pgquiles

4

Depende de cómo se abrió el archivo. Si se abre un archivo con bloqueo, no puede escribir ni cambiarle el nombre. Herramientas como Notepad ++ abren archivos sin bloquearlo. Si usted es el que abre y edita, se puede hacer eso también:

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

El código en el artículo muestra cómo utilizar un FileStream con opciones 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

Eso no funciona, mira mi C# sample – pgquiles

Cuestiones relacionadas