Перезапись существующего файла в C#


Я только что узнала о существовании этого форума, и это именно то, что мне нужно. Я просто задал этот вопрос на переполнение стека, и после прочтения ответов я придумал код (не тот, который я написал там, но одно я размещаю здесь).

Во-первых, это мои перепутались код:

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);

При сохранении в существующий файл, который находится в моем Dropbox, он, иногда, удалить исходный файл и не удается переместить временный файл в исходное местоположение в файле.Перемещение(tempFile, именем);. Так вот мой новый код, который я думаю, это никогда не должно, если операционная система не смутился и зло, удалить исходный файл без сохранения изменений новый. В худшем случае это происходит, что оригинал будет переименован и останется, что и я буду иметь, чтобы позволить пользователю знать (см. сообщение внизу):

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))
        {
            SafeXmlSerializer xmlFormatter = new SafeXmlSerializer(typeof(Project));
            xmlFormatter.Serialize(tempNewFileStream, Project);
        }

        if (File.Exists(fileName))
        {
            oldFileTempName = GetTempFileName(Path.GetDirectoryName(fileName));
            File.Move(fileName, oldFileTempName);
            originalRenamed = true;
        }

        File.Move(tempNewFile, fileName);
        originalRenamed = false;

        CurrentProjectPath = fileName;
    }
    catch (Exception ex)
    {
        exception = ex;
    }
    finally
    {
        if (tempNewFile != null) TryToDelete(tempNewFile);

        if (originalRenamed)
        {
            try
            {
                File.Move(oldFileTempName, fileName);
                originalRenamed = false;
            }
            catch { }
        }

        if (exception != null) MessageBox.Show(exception.Message);

        if (originalRenamed)
        {
            MessageBox.Show("'" + fileName + "'" +
                " have been corrupted or deleted in this operation.\n" +
                "A backup copy have been created at '" + oldFileTempName + "'");
        }
        else if (oldFileTempName != null) TryToDelete(oldFileTempName);
    }
}

Плеер.Математика.RandomDigits - это просто функция, которая возвращает строку со случайными цифрами. Вы думаете, что мой код, как я думаю или я чего-то не безопасно? Это трудно для меня, чтобы проверить все возможные исключения.



69785
10
c#
задан 24 марта 2011 в 04:03 Источник Поделиться
Комментарии
2 ответа


  • Мне не нравится, отбросив все исключения из файла.Удалить(). Я думаю, что это нормально, чтобы отменить здесь исключения directorynotfoundexception, но я думаю другие должны быть разрешены для распространения и будут показаны пользователю. Я считаю, что скрывая тот факт, что пользователь не имеет доступа для записи или другой процесс файл заблокирован, как правило, приводит к более запутанным ошибок в дальнейшем.

  • Вы serialise новый контент в большом попробовать-поймать. Если сериализация не работает, то вас сообщить пользователю, что файл был поврежден или удален и восстановить из резервной копии, при условии, хотя вы еще не достигли точки, где выполняется резервное копирование.

  • Идея одной большой попробовать-поймать, а затем, используя флаги, чтобы определить, на каком этапе вы были до это меня немного беспокоит. Вы можете заменить originalRenamed флаг с попробовать-поймать вокруг файла.Двигаться(tempNewFile, именем) , так как это только призыв, а флаг устанавливается в true.

    try
    {
    // ...

    try
    {
    File.Move(tempNewFile, fileName);
    }
    catch
    {
    if (!string.IsNullOrEmpty(oldFileTempName) && File.Exists(oldFileTempName))
    {
    File.Move(oldFileTempName, fileName);
    }

    MessageBox.Show("...");

    throw;
    }

    // ...

    if (!string.IsNullOrEmpty(oldFileTempName) && File.Exists(oldFileTempName))
    {
    TryToDelete(oldFileTempName);
    }
    }
    catch(Exception ex)
    {
    MessageBox.Show(ex.Message);
    }

    Это может быть неудобно, если вы хотите, чтобы окна сообщений появляются в определенном порядке, но я не думаю, что это должно быть слишком много проблемы.


4
ответ дан 24 марта 2011 в 07:03 Источник Поделиться

Используя Файл.Заменить() по-прежнему кажется лучшим вариантом для меня. Как вы сказали так, может дать проблемы:


Если sourcefilename и
destinationFileName находятся на разных
Тома, этот метод будет вызывать
исключение. Если
destinationBackupFileName на
разного объема от исходного файла,
файл резервной копии будет удален.

Чтобы предотвратить это исключение быть брошенным, может вы сначала проверьте, можно ли сериализовать в файл Temp непосредственно до нужного объема? Если это не возможно, дальнейшую обработку не удастся, так что можно уже показать сообщение о том, что объем не записи.

Затем, вызовите заменить функции, создание резервной копии файла. Когда это удается, должным образом обработать и проверить в каком состоянии ваши файлы, указать пользователю, когда что-то "продажных" (так указывают на файл резервной копии). В конце концов проверить, является ли файл резервной копии существует и удалить.

5
ответ дан 24 марта 2011 в 01:03 Источник Поделиться