5

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

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

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

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

  1. 创建 WindowsApplication 并在其上放置一个按钮控件。

  2. 在按钮单击事件处理程序中编写以下代码:

    私人无效按钮1_Click(对象发送者,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 的 Poweroff 按钮。

  4. 重新启动 PC 并检查文件。它包含以下文本:

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

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

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

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

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

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

NULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNUL

NUL 字符会出现在 Notepaad++ 中,而我们在普通记事本中看不到这些字符。

4

3 回答 3

3

那个会发生。当您首先附加一个文件时,它的大小在目录中被纠正(这在 NTFS 中是事务性的),然后写入实际的新数据。很有可能如果您关闭系统,您最终会得到一个附加大量空字节的文件,因为与元数据(文件大小)写入不同,数据写入不是事务性的。

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

于 2012-06-06T11:53:39.107 回答
3

我在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问题

于 2020-08-05T13:33:54.003 回答
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 行,则代码将写入 Array 的所有元素减去最后一个元素(NUL 行)

于 2014-09-26T19:29:16.600 回答