流编写器 在系统突然关闭时在文件末尾写入 NUL 字符
本文关键字:文件 NUL 字符 系统 突然 | 更新日期: 2023-09-27 18:36:20
我正在编写一些测试应用程序,以使用StreamWriter
将一些文本写入文本文件。执行WriteLine
方法时,系统突然关闭。重新启动计算机后,我观察到文件末尾有许多 NUL 字符。
我已经搜索了许多网站,包括MSDN,但没有找到这个问题的解决方案。
有人可以帮助我解决这个问题吗?
如果我们执行以下步骤,可以轻松重现:
-
创建 Windows应用程序并在其上放置一个按钮控件。
-
在按钮单击事件处理程序中,编写以下代码:
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(); }
-
运行应用程序并连续单击按钮(直到机器关闭才停止),然后按PC的电源关闭按钮。
-
重新启动 PC 并检查文件。它包含以下文本:
欢迎来到 C Sharp 编程世界,其中包含使用 IO 操作的测试应用程序。
欢迎来到 C Sharp 编程世界,其中包含使用 IO 操作的测试应用程序。
欢迎来到 C Sharp 编程世界,其中包含使用 IO 操作的测试应用程序。
欢迎来到 C Sharp 编程世界,其中包含使用 IO 操作的测试应用程序。
欢迎来到 C Sharp 编程世界,其中包含使用 IO 操作的测试应用程序。
欢迎来到 C Sharp 编程世界,其中包含使用 IO 操作的测试应用程序。
NULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNULNUL 字符将出现在 Notepaad++ 中,我们在普通记事本中看不到这些字符。
这种情况发生了。当您首先附加文件时,在目录中更正其大小(这在 NTFS 中是事务性的),然后写入实际的新数据。如果您关闭系统,您很有可能最终会得到一个附加了大量空字节的文件,因为数据写入与元数据(文件大小)写入不同,不是事务性的。
这个问题没有绝对的解决方案。
我在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 问题
它看起来很恶心,但这是我解决问题所必须做的。只需在将字符串写入文件后放置以下代码即可。
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 行)