首页 > 解决方案 > C# Windows 窗体无法将数据重写到文件

问题描述

我有一个应该将数据保存到文件的 Windows 窗体应用程序。为此,我称之为:

public void SaveVocabulary()
{
    string line;

    try
    {
        //create backup of file
        File.Copy(ConfigData.Filename, ConfigData.Filename.Replace(".txt", "_backup.txt"), true);

        // delete all content
        File.Create(ConfigData.Filename).Close();

        foreach (VocabularyData vocable in vocList)
        {
            line = vocable.VocGerman.Replace('|', '/') + "|";
            line += vocable.VocEnglish.Replace('|', '/') + "|";

            File.AppendAllText(ConfigData.Filename, line + Environment.NewLine);
        }

        // delete backup
        File.Delete(ConfigData.Filename.Replace(".txt", "_backup.txt"));
    }
    catch (Exception ex)
    {
        throw new Exception("Error saving Vocabulary: " + ex.Message, ex);
    }
}

但是每次我第二次通过该行时File.Create(ConfigData.Filename).Close();,代码都会抛出一个异常告诉我,我无法访问该文件,因为它被另一个进程使用。

Der Prozess kann nicht auf die Datei "C:\Users\some-path\Vocabulary.txt" zugreifen, da sie von einem anderen Prozess verwendet wird。

根据文档,该文件由File.AppendAllText. 我也尝试过StreamWriter明确地关闭它。这也引发了同样的异常。此外,没有其他人在使用该文件。(如果您知道在我的程序运行时阻止某人打开文件进行写入的方法,请告诉我该怎么做。)

请告诉我为什么会出现这种情况?保存后如何确保文件“免费”?所以我可以稍后再保存它。

编辑:这是我加载文件的方式:

public List<VocabularyData> LoadVocabulary()
{
    try
    {
        vocList = new List<VocabularyData>();

        string[] lines = File.ReadAllLines(GetFileName());
        string[] voc;
        VocabularyData vocable;

        foreach (string line in lines)
        {
            voc = line.Split('|');
            vocable = new VocabularyData();
            vocable.VocGerman = voc[0];
            vocable.VocEnglish = voc[1];
            vocable.CreationDate = DateTime.Parse(voc[2]);
            vocable.AssignedDate = DateTime.Parse(voc[3]);
            vocable.SuccessQueue = voc[4];
            vocable.TimeQueue = voc[5];

            vocList.Add(vocable);
        }
    }
    catch (Exception ex)
    {
        throw new Exception("Error loading  Vocabulary: " + ex.Message, ex);
    }

    return vocList;
}

标签: c#windowsformssystem.io.file

解决方案


让我们摆脱显式Streams ( File.Create(ConfigData.Filename).Close();) 并.Net为您完成工作:

using System.Linq;

...

// backup - same directory as ConfigData.Filename
//          same filename as ConfigData.Filename with _backup.txt suffix
string backUpName = Path.Combine(
  Path.GetDirectoryName(ConfigData.Filename),
  Path.GetFileNameWithoutExtension(ConfigData.Filename) + "_backup.txt");

File.Copy(ConfigData.Filename, backUpName, true);

// lines we want to save (see comments below)
var lines = vocList
  .Select(vocable => string.Join("|", // do not hardcode, but Join into line
     vocable.VocGerman.Replace('|','/'),
     vocable.VocEnglish.Replace('|', '/'),
     vocable.CreationDate.ToString("dd.MM.yyyy"),
     vocable.AssignedDate.ToString("dd.MM.yyyy"),
     vocable.SuccessQueue,
     vocable.TimeQueue,
     ""
   ));

File.WriteAllLines(ConfigData.Filename, lines);

File.Delete(backUpName);

编辑:文件读取例程可以简化

public List<VocabularyData> LoadVocabulary() {
  try {
    return File
      .ReadLines(GetFileName())
      .Where(line => !string.IsNullOrWhiteSpace(line)) // to be on the safe side
      .Select(line => line.Split('|'))
      .Select(voc => new VocabularyData() {
         VocGerman    = voc[0],
         VocEnglish   = voc[1],
         CreationDate = DateTime.Parse(voc[2]), 
         AssignedDate = DateTime.Parse(voc[3]),
         SuccessQueue = voc[4],
         TimeQueue    = voc[5]
       })
      .ToList();
  }
  catch (IOException ex) {
    //TODO: do not throw general Exception but derived 
    throw new InvalidOperationException($"Error loading Vocabulary: {ex.Message}", ex);
  }
}

推荐阅读