2012-04-24 25 views
6

De la documentación de File.Move:Mimic File.Move si el destino ya existe

Tenga en cuenta que si intenta reemplazar un archivo moviendo un archivo del mismo nombre en ese directorio, se obtiene una IOException. No puede usar el método Move para sobrescribir un archivo existente.

En resumen, no se puede sobrescribir en Move, por lo que con el fin de facilitar el sobreescribiendo el movimiento que imitan el comportamiento haciendo una File.Copy seguido de un File.Delete. Algo así como:

if (File.Exists(dstFileName)) 
{ 
    // System.IO.File.Move cannot be used to overwrite existing files, so we're going 
    // to simulate that behavior with a Copy & Delete. 
    File.Copy(procContext.FileName, dstFileName); 
    File.Delete(procContext.FileName); 
} 
else 
    File.Move(procContext.FileName, dstFileName); 

Mi pregunta es: ¿Hay alguna situación que deben protegerse contra lo que podría llevar al archivo de origen que se eliminen sin que primero se copia con éxito?

Según tengo entendido, al leer la documentación, dado que File.Copy no devuelve nada que arroje una excepción, en cualquier caso, no tiene éxito. ¿Alguien ha encontrado alguna situación en la que esto no sea cierto?

+3

¿No sería más seguro que hacer una eliminación en el archivo de destino si existe, seguido de un movimiento como lo hiciste inicialmente? – Tudor

+0

@Tudor - No necesariamente. Si el movimiento falla, el archivo de destino original también desaparecerá, lo que no es realmente el comportamiento esperado. –

+0

Pero de su pregunta deduzco que si mover le permitió sobrescribir el archivo si existe, lo usaría, en lugar de copiar + eliminar. Entonces supongo que estás dispuesto a correr ese riesgo. – Tudor

Respuesta

7

Le sugiero que pruebe primero si el archivo de destino existe y, en caso afirmativo, elimínelo. Luego ejecuta una operación de movimiento normal.

Dado que esta secuencia no es atómica, en caso de que exista el destino, es posible que desee cambiarle el nombre en lugar de eliminarlo, para evitar perderlo en caso de que el movimiento falle.

+0

Gracias de nuevo por su ayuda. –

+1

Sin embargo, esto no es una operación atómica. Es decir. si estamos en el medio de la eliminación y moviendo ese archivo y ocurre una falla de energía, perdemos el contenido. Esto no es hipotético, sino un problema real que tenemos con una de nuestras aplicaciones. Consulte la respuesta a continuación, utilizando File.Replace() en su lugar – Seven

+0

Si, como la mayoría de las personas que hacen esta pregunta, necesita atomicidad, consulte [Arsen Zahray's answer] (http://stackoverflow.com/a/21882993/429091). – binki

2

Esto es seguro. File.Copy tendrá éxito o lanzará. Por supuesto, la eliminación podría fallar dejando el archivo de origen como basura.

Si su computadora falla, sin embargo, no hay garantía de que la operación de copia haya endurecido aún más los datos. Puede perder datos en ese caso.

Durante las operaciones normales, esto es seguro.

3

Es difícil simular una operación atómica si el sistema operativo no le proporciona buenas operaciones atómicas. Move es atómico en algunos, pero no en todos los sistemas de archivos, pero no cuando se mueve el disco al disco.

En el caso del mismo disco, Delete + Move es algo elegante (rápido y seguro) ya que realmente no rellena los datos de ninguna manera. Se podría ampliar aún más a

try 
{ 
    Move(dest, tmp); 
    Move(src, dest); 
    Delete(tmp); 
} 
catch 
{ 
    try 
    { 
     Move(tmp, dest); 
    } 
    catch 
    { 
    } 
    throw; 
} 

(Esto hace que sea menos probable que va a perder el archivo de destino cuando, por ejemplo, no tiene los derechos necesarios para finalizar el movimiento.)

En un escenario donde no sabes que es el mismo disco, tu solución es lo suficientemente segura y simple. Sin embargo, copia los datos incluso dentro del mismo disco, lo que le brinda una ventana más amplia de riesgo de un corte de energía.

0

Compruebe si el archivo "Destino" Exsists. Si no, copie su archivo.

En caso afirmativo: Mueva "Destino" a directorio temporal, donde puede estar seguro, que la jugada será exitosa. Puede generar un subdirectorio en Temp con el nombre auf an UUID. Luego copia tu archivo.

5

La forma correcta de hacerlo sería llamar

File.Replace(source, destination, copy) 

Eso hace el truco para mí

+0

¿Sabe si File.Replace está copiando datos bajo el capó, o simplemente está actualizando las referencias del sistema de archivos (como un movimiento)? Más específicamente, ¿será tan rápido como un movimiento cuando la fuente y el destino están en el mismo disco y la copia es nula? – yoyo

+1

Sí, parece ser una operación atómica (o al menos transaccional). Ver https://social.msdn.microsoft.com/forums/vstudio/en-US/848ce6b7-ce52-43ca-b79b-168835837c63/is-filereplace-atomic-on-an-ntfs-filesystem – Seven

+0

Oh, entonces * esto * es lo que se llama a 'rename()' en .net. – binki

Cuestiones relacionadas