【问题标题】:Writing to a text file in AppData doesn't work - C#在 AppData 中写入文本文件不起作用 - C#
【发布时间】:2017-03-19 00:02:42
【问题描述】:

我正在使用以下代码行将用户凭据写入文本文件。它应该在 AppData 中创建目录(它会这样做),但它不会将凭据写入文本文件,而是将其留空!

public void RegisterUserCreds()
{
    string[] creds = { Username.Text, Password.Text };
    string roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
    if (!Directory.Exists(roaming + "/Launcher")) 
        Directory.CreateDirectory(roaming + "/Launcher");
    string specificFolder = roaming + "/Launcher/user_info.txt";
    var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite);
    var sw = new StreamWriter(fs);
    sw.WriteLine(Username.Text);
    fs.Close();
}

有什么问题?谢谢!

【问题讨论】:

    标签: c# file text appdata


    【解决方案1】:

    在流上操作时只需使用using statement

    public static void RegisterUserCreds()
    {
        string[] creds = { Username.Text, Password.Text };
        string roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
        if (!Directory.Exists(roaming + "/Launcher")) Directory.CreateDirectory(roaming + "/Launcher");
        string specificFolder = roaming + "/Launcher/user_info.txt";
        using (var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite))
        {
            using (var sw = new StreamWriter(fs))
            {
                sw.WriteLine(Username.Text);
            }
        }
    }
    

    在您的代码中,您在流编写器能够刷新您要写入的更改之前关闭文件流,因此文件被创建为空。

    【讨论】:

      【解决方案2】:

      您关闭了错误的流。当您创建新的流对象并将现有流传递给构造函数时,该新流现在“拥有”旧流。当您处置较新的流时,它会自动处置较旧的流。

      在您的情况下,您正在关闭“fs”流,但“sw”流可能还没有真正写入它(它有自己的内部缓冲区)。如果您要关闭“sw”流,它会刷新它的缓冲区(进入“fs”流),然后它会调用 fs.Dispose() 以确保它执行相同的操作。

      有一个更好的方法,它可以帮助您避免像这样无序地做事,并确保您调用Dispose(),即使抛出异常(流实现IDisposable,所以您'应该总是在你完成它们后调用他们的Dispose() 方法,以便他们可以在内部“清理”)。 using 语句非常适合这种情况,因为即使抛出异常,它也会调用 Dispose()(这是用 try/finally 块包装代码的快捷方式):

      using (var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite))
      {
          using (var sw = new StreamWriter(fs))
          {
              sw.WriteLine(Username.Text);
          }
      }
      

      这个和这个是一样的:

      try
      {
          var fs = File.Open(specificFolder, FileMode.OpenOrCreate, FileAccess.ReadWrite);
          try
          {
              var sw = new StreamWriter(fs);
              sw.WriteLine(Username.Text);
          }
          finally
          {
              sw.Dispose();
          }
      }
      finally
      {
          fs.Dispose();
      }
      

      即使sw.Dispose() 会为您调用fs.Dispose(),再次调用fs.Dispose() 也没有什么坏处。为什么调用 Dispose() 很重要?假设在sw.WriteLine() 期间引发了异常(例如,磁盘空间不足、I/O 错误等)...文件将保持打开状态,直到您的应用程序终止。 using(或 try/catch 版本)将确保无论如何关闭文件。

      (旁注:对于流,Dispose()Close() 做同样的事情,你不需要同时调用两者。Close() 只需调用 Dispose() -- MS 包含一个名为 Close() 的方法,因为这是人们习惯使用文件 API 的方式,但 .NET IDisposable 接口使用了一种称为 Dispose() 的方法

      (另一个注意事项:从 .NET 4.5 开始,许多流类都有一个额外的构造函数,它有一个新的“leaveOpen”参数...传递 true 会告诉该流不会自动处理原始流)

      【讨论】:

        猜你喜欢
        • 2017-04-01
        • 2013-12-20
        • 1970-01-01
        • 2011-05-10
        • 1970-01-01
        • 2018-11-13
        • 2018-03-27
        相关资源
        最近更新 更多