HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpMinor

Overwriting an existing file in C#

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
existingfileoverwriting

Problem

I just found out about the existence of this forum and it's exactly what I needed. I just asked this question on Stack Overflow and after reading the answers I came up with a code (not the one I posted there but the one I'm posting here).

First, this is my messed up code:

string tempFile = Path.GetTempFileName();

using (Stream tempFileStream = File.Open(tempFile, FileMode.Truncate))
{
    SafeXmlSerializer xmlFormatter = new SafeXmlSerializer(typeof(Project));
    xmlFormatter.Serialize(tempFileStream, Project);
}

if (File.Exists(fileName)) File.Delete(fileName);
File.Move(tempFile, fileName);
if (File.Exists(tempFile)) File.Delete(tempFile);


When saving to an existing file that is in my Dropbox, it will, sometimes, delete the original file and fail to move the temporary file to the original location in File.Move(tempFile, fileName);. So here is my new code that I think it should never, unless the OS became self-conscious and evil, delete the original file without saving the new one. The worst it can happens is that the original will be renamed and will stay like that and I will have to let the user know (see the MessageBox at the bottom):

```
private string GetTempFileName(string dir)
{
string name = null;
int attempts = 0;
do
{
name = "temp_" + Player.Math.RandomDigits(10) + ".hsp";
attempts++;
if (attempts > 10) throw new Exception("Could not create temporary file.");
}
while (File.Exists(Path.Combine(dir, name)));

return name;
}

private void TryToDelete(string path)
{
try { File.Delete(path); }
catch { }
}

private void SaveProject(string fileName)
{
bool originalRenamed = false;
string tempNewFile = null;
string oldFileTempName = null;
Exception exception = null;

try
{
tempNewFile = GetTempFileName(Path.GetDirectoryName(fileName));

using (Stream tempNewFileStream = File.Open(tempNewFile, FileMode.CreateNew))
{
SafeXmlSeri

Solution

Using File.Replace() still seems the best option to me. As you mentioned on SO, the following might give a problem:


If the sourceFileName and
destinationFileName are on different
volumes, this method will raise an
exception. If the
destinationBackupFileName is on a
different volume from the source file,
the backup file will be deleted.

To prevent this exception from being thrown, can't you first check whether you can serialize the temp file directly to the desired volume? If this isn't possible, further processing will fail as well, so you can already show a message that the volume isn't writeable.

Afterwards, call the Replace function, creating a backup file. When it fails, handle appropriately and check in which state your files are, indicate to the user when something is 'corrupt' (so point to the backup file). In the finally check whether the backup file exists and remove.

Context

StackExchange Code Review Q#1420, answer score: 5

Revisions (0)

No revisions yet.