为什么StreamWriter会覆盖我的文件?

5
我正在使用SteamWriter将内容写入文本文件,但是它会用新数据覆盖旧数据。 我该如何确保只添加新数据而不是覆盖旧数据?
我的代码:
class Program
{
    const string filename = @"C:\log.txt";
    static void Main()
    {
        FileStream fs;
        fs = new FileStream(filename, FileMode.Create, FileAccess.Write);
        StreamWriter writer = new StreamWriter(fs);
        writer.WriteLine("test");

        writer.Close();
        fs.Close();
    }
}

顺便提一下,我会使用 using 而不是在结尾处使用那个丑陋的关闭语句。using (var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) { using(var writer = new StreamWriter(fs)) { writer.WriteLine("test"); } } - Stacked
5个回答

12
如果您使用FileMode.Create根据MSDN的说法
指定操作系统应该创建一个新文件。如果文件已经存在它将被覆盖。这需要FileIOPermissionAccess.Write权限。FileMode.Create等同于请求:如果文件不存在,则使用CreateNew;否则,使用Truncate。如果文件已经存在但是是一个隐藏文件,则会抛出UnauthorizedAccessException异常。
因此,如果您想要将内容添加到文件末尾,您需要使用FileMode.Append

打开文件如果它存在寻找到文件的末尾,或创建一个新文件。这需要FileIOPermissionAccess.Append权限。FileMode.Append只能与FileAccess.Write一起使用。试图寻找到文件末尾之前的位置会引发IOException异常,并且任何读取尝试都会失败并引发NotSupportedException异常。

FileStream fs = new FileStream(filename, FileMode.Append, FileAccess.Write);

文档不太清楚,“它将被覆盖”是否意味着文件中的现有字节将被保留,仅被每次新写入的数据覆盖(即从文件开头覆盖当前数据)或者在写入新数据之前整个文件都会被截断。 - Dai

1
要追加到文件中,您可以将流的位置更新到末尾。
...
using (FileStream fs = new FileStream(filename, FileMode.OpenOrCreate, FileAccess.Write))
{
    fs.Seek(0, SeekOrigin.End);
    using (StreamWriter writer = new StreamWriter(fs))
    {
        // To append, update the stream's position to the end of the file
        writer.WriteLine("test");
    }
}
...

顺便提一下,如果您打算覆盖文件,并且原始文件的长度大于您需要的新数据的长度,则在写出文件后,需要对底层文件流使用SetLength()。换句话说,

    ...
    {
        writer.WriteLine("test");
        fs.SetLength(fs.Position);
    }
    ...

我认为你的意思是 FileMode.OpenOrCreate,因为 FileMode.Create 会覆盖文件,并且在使用 FileStream 创建 StreamWriter 之前应该先进行 fs.Seek - Brett Caswell
谢谢指出,我一直在跟随原帖的代码,所以没有停下来思考过那个问题!谢谢。 - Wes

0

试试这个

string path = your file path;
   using(StreamWriter sw = new StreamWriter(path,true))
           {

                    sw.WriteLine("string here");
           }

这里的 flush 不必要 - close 会自动 flush。 - Steffan Donal
虽然我必须说我不同意您打开文件的方法。 我会使用 using(StreamWriter sW = new StreamWriter("FILE", true)){ - Steffan Donal
现在这段代码已经出错了。请移除 using 语句内的两个 if,并在 true) 后添加一个 ) - Steffan Donal
@Ruirize 现在怎么样?我没有集成开发环境(IDE)来测试它,抱歉。 - Karthik

0
fs = new FileStream(filename, FileMode.Append, FileAccess.Write);

0

正如其他人指出的问题,我想提出一个更简单的解决方案

File.AppendAllText(filename, "test");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接