Estoy trabajando en un software de servidor que periódicamente necesita guardar datos en el disco. Necesito asegurarme de que el archivo anterior se sobrescribe y que el archivo no se corrompe (por ejemplo, solo se sobrescribe parcialmente) en caso de circunstancias inesperadas.Almacenamiento de archivos confiable (File.Replace) en un entorno ocupado
He adoptado el siguiente patrón:
string tempFileName = Path.GetTempFileName();
// ...write out the data to temporary file...
MoveOrReplaceFile(tempFileName, fileName);
... donde MoveOrReplaceFile es:
public static void MoveOrReplaceFile(string source, string destination) {
if (source == null) throw new ArgumentNullException("source");
if (destination == null) throw new ArgumentNullException("destination");
if (File.Exists(destination)) {
// File.Replace does not work across volumes
if (Path.GetPathRoot(Path.GetFullPath(source)) == Path.GetPathRoot(Path.GetFullPath(destination))) {
File.Replace(source, destination, null, true);
} else {
File.Copy(source, destination, true);
}
} else {
File.Move(source, destination);
}
}
Esto funciona bien siempre y cuando el servidor tiene acceso exclusivo a los archivos. Sin embargo, File.Replace parece ser muy sensible al acceso externo a los archivos. En cualquier momento en mi software se ejecuta en un sistema con un antivirus o un sistema de copia de seguridad en tiempo real, los errores aleatorios File.Replace empiezan a saltar:
System.IO.IOException: No se puede eliminar el archivo se va a sustituir.
Estas son algunas de las posibles causas que he eliminado:
- archivo inédito maneja: utilizando() asegura que todos los identificadores de archivo son liberados tan pronto como sea posible.
- Problemas de subprocesamiento: lock() guarda todo el acceso a cada archivo.
- Diferentes volúmenes de disco: File.Replace() falla cuando se usa en todos los volúmenes de disco. Mi método ya lo comprueba y vuelve a File.Copy().
Y aquí están algunas sugerencias que me he encontrado, y por qué prefiero no los uso:
- Volume Shadow Copy Service: Esto sólo funciona siempre y cuando la tercera problemática El software de la parte (monitores de respaldo y antivirus, etc.) también usa VSS. El uso de VSS requiere toneladas de P/Invoke, y tiene problemas específicos de la plataforma.
- Bloqueando archivos: En C#, bloquear un archivo requiere mantener un FileStream abierto. Esto mantendría fuera el software de terceros, pero 1) Todavía no podré reemplazar el archivo usando File.Replace, y 2) Como mencioné anteriormente, prefiero escribir en un archivo temporal primero, para evitar accidentes. corrupción.
Agradecería cualquier entrada para hacer que File.Replace funcione siempre o, más generalmente, guardar/sobrescribir archivos en el disco de manera confiable.
¿Espera 'MoveOrReplaceFile' a estudiarse a la vez (lo que significa visitada por múltiples hilos de su aplicación * * o incluso de varias instancias de la aplicación)? –
Mi propio código nunca llama a MoveOrReplaceFile al mismo tiempo, pero hay otros procesos fuera de mi control que pueden intentar leer el archivo. Esos accesos de lectura aleatoria son los que hacen que File.Replace falle. – matvei