Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# close stream and delete file if something failed

Tags:

c#

filestream

I'm working with a file stream in C#. It's a storage cache, so if something goes bad writing the file (corrupted data, ...), I need to delete the file and rethrow the exception to report the problem. I'm thinking on how to implement it in the best way. My first attempt was:

Stream fileStream = null;
try
{
    fileStream = new FileStream(GetStorageFile(),
        FileMode.Create, FileAccess.Write, FileShare.Write);
    //write the file ...
}
catch (Exception ex)
{
    //Close the stream first
    if (fileStream != null)
    {
      fileStream.Close();
    }
    //Delete the file
    File.Delete(GetStorageFile());
    //Re-throw exception
    throw;
}
finally
{
    //Close stream for the normal case
    if (fileStream != null)
    {
      fileStream.Close();
    }
}

As you will see, if something goes bad writing the file, the fileStream will be closed twice. I know that it works, but I don't think that is the best implementation.

I think that I could remove the finally block, and close the stream in the try block, but I have posted this here because you guys are experts and I want to hear the voice of an expert.

like image 656
Daniel Peñalba Avatar asked Nov 24 '10 06:11

Daniel Peñalba


2 Answers

If you put the fileStream in a using block you don't need to worry about closing it, and then just leave the cleaning up (deleting of the file in the catch block.

try 
{ 
    using (FileStream fileStream = new FileStream(GetStorageFile(), 
        FileMode.Create, FileAccess.Write, FileShare.Write))
    {
        //write the file ... 
    }
} 
catch (Exception ex) 
{ 
    File.Delete(GetStorageFile()); 
    //Re-throw exception 
    throw; 
} 
like image 61
BBoy Avatar answered Sep 29 '22 11:09

BBoy


I believe what you want is this:

var fs = new FileStream(result.FilePath, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);

I've used it with ASP.Net to have the web server return a result to a temp file that's on disk, but to make sure it's cleaned up after the web server finishes serving it to the client.

public static IActionResult TempFile(string tempPath, string mimeType, string fileDownloadName)
        {
            var fs = new FileStream(tempPath, FileMode.Open, FileAccess.Read, FileShare.None, 4096, FileOptions.DeleteOnClose);
            var actionResult = new FileStreamResult(fileStream: fs, contentType: mimeType)
            {
                FileDownloadName = fileDownloadName
            };

            return actionResult;
        }
like image 22
Adam Tegen Avatar answered Sep 28 '22 11:09

Adam Tegen