在AppData中写入文本文件不会';t工作-C#

在AppData中写入文本文件不会';t工作-C#,c#,file,text,appdata,C#,File,Text,Appdata,我使用以下代码行将用户的凭据写入文本文件。它应该在AppData中创建目录(确实如此),但它不会将凭据写入文本文件,而是将其保留为空 public void RegisterUserCreds() { string[] creds = { Username.Text, Password.Text }; string roaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);

我使用以下代码行将用户的凭据写入文本文件。它应该在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();
}
有什么问题吗?谢谢

在流上操作时只需使用:

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

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

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

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

有一种更好的方法,可以帮助您避免像这样无序地执行操作,并且确保即使抛出异常,您也在调用
Dispose()
(流实现
IDisposable
),因此在处理完它们之后,您应该始终调用它们的
Dispose()
方法,以便它们可以在内部调用“clean up”)。
using
语句非常适合于此,因为即使引发异常,它也会调用
Dispose()
(这是用try/finally块包装代码的快捷方式):

这与此相同:

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错误等)…该文件将保持打开状态,直到您的应用程序终止。使用(或try/catch版本)的
将确保无论发生什么情况,该文件都已关闭

(旁注:对于streams,
Dispose()
Close()
执行相同的操作,您不需要同时调用这两个函数。
Close()
只需调用
Dispose()
——MS包含了一个名为
Close()的方法)
因为人们习惯于使用文件API,但是.NET
IDisposable
接口使用了一个名为
Dispose()
的方法

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

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