StreamWriter当系统突然关闭时,在文件末尾写入NUL字符

时间:2012-06-06 11:49:36

标签: shutdown streamwriter

我正在编写一些测试应用程序,使用StreamWriter将一些文本写入文本文件。执行WriteLine方法时系统突然关闭。重新启动后,机器发现文件末尾有许多NUL字符。

搜索了很多网站,包括MSDN,我没有找到解决此问题的方法。

任何人都可以帮我解决这个问题。

如果我们执行以下步骤,这很容易重现:

  1. 创建WindowsApplication并在其上放置一个按钮控件。
  2. 在按钮单击事件处理程序中,编写以下代码:

    private void button1_Click(object sender,EventArgs e)

    {
        string str = "Welcome to the C Sharp programming world with a test application using IO operations.";
        StreamWriter sw = new StreamWriter(fileName, true, Encoding.Unicode, str.Length);
        sw.WriteLine(str);
        sw.Close();        
    } 
    
  3. 运行应用程序并连续单击按钮(不要直到机器关闭)并按下PC的电源按钮。

  4. 重新启动电脑并检查包含以下文字的文件:

  5. 欢迎使用使用IO操作的测试应用程序来访问C Sharp编程世界。

    欢迎使用使用IO操作的测试应用程序来访问C Sharp编程世界。

    欢迎使用使用IO操作的测试应用程序来访问C Sharp编程世界。

    欢迎使用使用IO操作的测试应用程序来访问C Sharp编程世界。

    欢迎使用使用IO操作的测试应用程序来访问C Sharp编程世界。

    欢迎使用使用IO操作的测试应用程序来访问C Sharp编程世界。

    NULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNUL

    NUL字符将出现在NotePad ++中,我们无法在Normal NotePad中看到这些字符。

    先谢谢

3 个答案:

答案 0 :(得分:2)

发生这种情况。首先附加文件时,在目录中更正其大小(并且在NTFS中是事务性的),然后写入实际的新数据。很有可能如果你关闭系统,你最终会得到一个附加大量空字节的文件,因为数据写入不是事务性的,不像元数据(文件大小)写入。

这个问题没有绝对的解决办法。

答案 1 :(得分:2)

我在Linux(在树莓派上)上的 netcore 遇到了同样的问题。看起来它们是某种未及时刷新的缓冲区。 (StreamWriter.Flush()方法无济于事。)

解决方法是将缓冲区大小设置为数据大小array.Length,并使用FileOptions.WriteThrough禁用所有缓存(来自msdn:)

指示系统应该通过任何中间高速缓存写入 并直接转到磁盘。

string str = "Welcome to the C Sharp programming world with a test application using IO operations.";
byte[] data = new UTF8Encoding(true).GetBytes(str);
using (FileStream fs = new FileStream(fileName, FileMode.Append, FileAccess.Write,
                                FileShare.Read, data.Length, FileOptions.WriteThrough))
{                    
    fs.Write(data , 0, data.Length);
}

对于来自C / C ++的用户,请设置posix标志:

O_DIRECT尝试最大程度减少往返于此的I / O的缓存影响 文件。通常,这会降低性能,但在 特殊情况,例如应用程序自行缓存时。 文件I / O直接在用户空间缓冲区中进行,也可以从用户空间缓冲区中进行。

更多信息:SO question

答案 2 :(得分:0)

我知道它看起来很糟糕,但这是我必须要解决的问题。将字符串写入文件后,只需输入以下代码即可。

var lines = System.IO.File.ReadAllLines(workingFile.FullName);

//Strip the "null line" from file
if (lines[lines.Length - 1].StartsWith("\0\0\0\0\0"))
{
    System.IO.File.WriteAllLines(workingFile.FullName, lines.Take(lines.Length - 1).ToArray());
}

这样做是将文件中的所有行读入一个数组,如果最后一行是那个讨厌的NUL行,代码将写入数组的所有元素减去最后一个元素(NUL行)