Как безопасно сохранить данные в существующий файл с помощью C #?

Как безопасно сохранить данные в файл, который уже существует в 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 , иногда я получаю исключение, сообщающее мне, что невозможно сохранить в уже существующий файл. Судя по всему, первый File.Delete (fileName); удалил файл не сразу, а через некоторое время. Итак, я получил исключение в File.Move (tempFile, fileName); , потому что файл существовал, а затем файл был удален, а мой файл потерялся.

Я использовал другие приложения с файлами в моем Dropbox, и им каким-то образом удается не испортить его. Когда я пытаюсь сохранить файл в папке Dropbox, иногда я получаю сообщение о том, что файл уже используется, и тому подобное, но у меня никогда не было проблем с удалением файла.

Так что бы это будет стандарт / лучшая практика?

Хорошо, это то, что я придумал после прочтения всех ответов:

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 SaveProject(string fileName)
{
    bool originalRenamed = false;
    string tempNewFile = null;
    string oldFileTempName = 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)
    {
        MessageBox.Show(ex.Message);
    }
    finally
    {
        if(tempNewFile != null) File.Delete(tempNewFile);

        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) File.Delete(oldFileTempName);
    }
}

Player.Math. RandomDigits - это всего лишь небольшая функция, которую я сделал, которая создает строку из n случайных цифр.

Я не понимаю, как это могло испортить исходный файл, если ОС не сработает. Это довольно близко к ответу Ганса, за исключением того, что я сначала сохраняю файл во временный файл, чтобы, если что-то пойдет не так при сериализации, мне не нужно переименовывать файл обратно в его исходное имя, что также может пойти не так. Пожалуйста! дайте мне знать, если найдете ошибку.

13
задан Juan 22 March 2011 в 20:20
поделиться