2012-08-23 51 views
5

Im tratando de escribir en un recurso compartido de red (local) mediante TFilestream. Todo funciona bien si la conexión de red no se interrumpe.Delphi escribiendo en un recurso compartido de red utilizando TFilestream bloquea el archivo cuando se pierde la red

Sin embargo, si desenchufo el cable de red y luego lo vuelvo a conectar, los intentos subsiguientes de abrir la secuencia de archivos fallan debido a restricciones de acceso. ¡Tampoco puedo borrar el archivo en el explorador! Parece que TFilestream bloquea el archivo y la única forma de evitar esto es reiniciar.

En mi aplicación, mantengo el archivo abierto todo el tiempo que escribo (es un archivo de registro escrito una vez por segundo).

Mi código que falla es el siguiente:

procedure TFileLogger.SetLogFilename(const Value: String); 
var line : String; 
Created : Boolean; 
begin 
    if not DirectoryExists(ExtractFilePath(Value)) then //create the dir if it doesnt exist 
    begin 
     try 
     ForceDirectories(ExtractFilePath(Value)); 
     except 
     ErrorMessage(Value); //dont have access to the dir so flag an error 
     Exit; 
     end; 
    end; 
    if Value <> FLogFilename then //Either create or open existing 
    begin 
     Created := False;   
     if Assigned(FStream) then 
     FreeandNil(FStream); 
     if not FileExists(Value) then //create the file and write header 
     begin 
      //now create a new file 
      try 
       FStream := TFileStream.Create(Value,fmCreate); 
       Created := True; 
      finally 
      FreeAndNil(FStream); 
      end; 
      if not Created then //an issue with creating the file 
      begin 
       ErrorMessage(Value); 
       Exit; 
      end; 
      FLogFilename := Value; 
      //now open file for writing 
      FStream := TFileStream.Create(FLogFilename,fmOpenWrite or fmShareDenyWrite); 
      try 
       line := FHeader + #13#10; 
       FStream.Seek(0,soFromEnd); 
       FStream.Write(Line[1], length(Line)); 
       FSuppress := False; 
      except 
       ErrorMessage(Value); 
      end; 
     end else begin //just open it 
      FLogFilename := Value; 
      //now open file for writing 
      FStream := TFileStream.Create(FLogFilename,fmOpenWrite or fmShareDenyWrite); //This line fails if the network is lost and then reconnected 
     end; 
    end; 
end; 

Si alguien tiene algún consejo sería apreciado.

+0

¿Es esto realmente un problema con TFileStream? Si es así, simplemente usa algo más, como CreateFile. –

Respuesta

0

Hago algo similar, pero no uso TFileStream. Utilizo métodos de archivos desde SysUtils. Aquí es básicamente lo que hago, adaptado a su situación:

// variables used in pseudo-code below 
var 
    fHandle, bytesWriten: Integer; 
    Value: string; 
  • Abrir el archivo de salida usando fHandle := FileOpen('filename', fmOpenReadWrite or ...).
  • Verify es fHandle > -1, sleep y loop si no lo está.
  • Escribe la salida bytesWritten := FileWrite(fHandle, Value, Length(Value));.
  • Compruebe el bytesWritten, deberían = Length(Value).
  • Si el bytesWritten es 0, sabrá que el identificador del archivo se perdió. Puse un bloque try ... finally alrededor de todo mi código y ejecuto if fHandle > -1 then try FileClose(fHandle); except end; para que fuerce al sistema a liberar el identificador del archivo, incluso si el archivo ya no está accesible.
  • Si el bytesWritten fue 0, espere unos segundos y vuelva a intentarlo.

Parece como si tuviera un problema similar al describir hasta que he añadido el código:

if fHandle > -1 then 
    try 
    FileClose(fHandle); 
    except 
    end; 

He copiado archivos gigabyte a un mando a distancia (lento) compartido de red mediante este enfoque, y la red compartir se ha perdido varias veces durante la copia. Puedo reanudar la copia tan pronto como la red compartida esté disponible nuevamente. Debería poder hacer algo similar con su archivo de registro ...

+4

Esta no es la respuesta. ¿Qué pasa si la red nunca regresa? Ahora tu programa está colgado en un bucle ocupado. FWIW no necesita usar la antigua API de archivos, ese código podría escribirse fácilmente con un TFileStream. –

+0

El código que diseñé para este tiene un número máximo de intentos para que no se bloquee en un bucle ocupado; eso es fácil de agregar. No sabía si TFileStream y la antigua API de archivos manejaban las cosas de manera diferente y si eso podía ser parte del problema. Como sé que funciona con el archivo API, quería que Simon supiera cómo funciona esa opción ... –

Cuestiones relacionadas