如何使用C#安全地将数据保存到现有文件? [英] How to safely save data to an existing file with C#?

查看:114
本文介绍了如何使用C#安全地将数据保存到现有文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何安全地将数据保存到C#中已存在的文件中?我有一些数据序列化到一个文件,我很确定直接保存到文件不是一个好主意,因为如果出现任何问题,文件将被破坏,以前的版本将丢失。

How do you safely save data to a file that already exists in C#? I have some data that is serialized to a file and I'm pretty sure is not a good idea to safe directly to the file because if anything goes wrong the file will get corrupted and the previous version will get lost.

所以这就是我到目前为止所做的:

So this is what I've been doing so far:

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); 中得到一个例外,因为该文件存在,然后文件被删除,我的文件丢失了。

The problem is that when I tried to save to a file that was in my Dropbox, sometimes I got an exception telling me that it cannot save to a file that already exists. Apparently the first File.Delete(fileName); didn't delete the file right away but after a little bit. So I got an exception in the File.Move(tempFile, fileName); because the file existed and then the file got erased and my file got lost.

我已经将其他应用程序与Dropbox中的文件一起使用,不知怎的,他们设法不搞乱它。当我试图保存到我的Dropbox文件夹中的文件时,有时我会收到一条消息,告诉我该文件正在被使用或类似的东西但我从未遇到过要删除文件的问题。

I've used other applications with files in my Dropbox and somehow they manage to not mess it up. When I'm trying to save to a file in my Dropbox folder, sometimes I get a message telling me that the file is being used or stuff like that but I never had a problem with a file being erased.

那么这里的标准/最佳做法是什么?

So what would it be the standard / best practice here?

确定这是我在阅读完所有答案后想出来的:

OK this is what I came up with after reading all answers:

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个随机数字的字符串。

Player.Math.RandomDigits is just a little function I made that creates an string with n random digits.

我看不出这怎么会弄乱原来的文件,除非操作系统正在进行wacko。它与Hans的答案非常接近,除了我首先将文件保存到临时文件中,这样,如果在序列化时出现问题,我不需要将文件重命名为它的原始名称,这也可能出错。请!如果你发现任何缺陷,请告诉我。

I don't see how could this mess up the original file unless the OS is going wacko. It's pretty close to Hans's answer except that I first save the file to a temporary file so that, if something goes wrong when serializing, I don't need to rename the file back to it's original name, which can also go wrong. Please! let me know if you find any flaw.

推荐答案

我不确定这是多么安全,但假设你的操作系统不是'崩溃,猜怎么着?有一个应用程序: File.Replace

I'm not sure how secure this is, but assuming your OS isn't crashing, guess what? There's an app for that: File.Replace

File.Replace(tempFile, fileName, backupFileName);






我认为你真的交易;只有这样才能保证不会丢失数据。有关.NET解决方案,请查看这篇文章,但要注意它可能是一个比简单的文件替换解决方案更难使用。


I think what you really need in a critical situation is transactions; only then can you guarantee against the loss of data. Take a look at this article for a .NET solution, but be aware that it might be a bit harder to use than a simple file replacement solution.

这篇关于如何使用C#安全地将数据保存到现有文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆