我曾经使用以下函数写入许多不同的文件
using (FileStream fs = new FileStream(Settings.PsLog, FileMode.Truncate, System.Security.AccessControl.FileSystemRights.Write, FileShare.ReadWrite, 1024, FileOptions.None, null))
{
foreach (string line in checkList)
{
byte[] encodedText = Encoding.Unicode.GetBytes(line + Environment.NewLine);
await fs.WriteAsync(encodedText, 0, line.Length);
}
}
由于此代码是全部复制粘贴的,我决定将其提取为更通用的功能。
private static async Task WriteTextAsync(string filePath, string text)
{
byte[] encodedText = Encoding.Unicode.GetBytes(text + Environment.NewLine);
using (FileStream sourceStream = new FileStream(filePath,
FileMode.Append, FileAccess.Write, FileShare.Write,
bufferSize: 1024, useAsync: true))
{
await sourceStream.WriteAsync(encodedText, 0, encodedText.Length);
};
}
然而,在使用提取的版本后,随机NUL将附加到文本
这些空值来自哪里?我也尝试将filestream()
设置1复制为1,但即便如此,也发生了NUL。
答案 0 :(得分:4)
您的原始代码已损坏。
使用Encoding.Unicode
时,line.Length
与encodedText.Length
不同。当您尝试写入数据时,您只会写一半(平均)。
由于在您的示例中实际上并未发生这种情况,最可能的原因是您实际上并未使用Encoding.Unicode
,而是使用Encoding.UTF8
或其中一个字节ANSI / ASCII编码。
在任何一种情况下,请确保编写尽可能多的字节来写入。字符数无关紧要。并确保使用正确的编码 - 只能有一个。
作为旁注,您的代码也会比原始代码慢得多。这很可能是一次糟糕的权衡。相反,您可能希望捕获整个foreach
,并传递IEnumerable<string>
而不是string
。如果你真的只需要在某些情况下写一个字符串,你可以提供params string
重载或任何最适合你的方法。并且确保所有情况都是等效的 - 这个肯定不是,因为原始文件在原始代码中被丢弃,而它只会附加到您的代码中。
答案 1 :(得分:0)
也许您正在编写UTF-16输出?
精化:
在您的问题的第一个和第二个代码块中,您使用的是Encoding.Unicode
,它将字符串编码为little endian UTF-16 byte representations。小端字节顺序UTF-16表示ASCII字符(如0
或G
)包含通常的ASCII字节作为第一个字节,然后0
(NUL
)作为第二个字节字符的字节。这可能是输出中NUL
个字节的来源。
至于为什么NUL
没有出现在第一个代码块的输出中,我不确定。请发布一个输入字符串,该字符串不会为第一个代码块输出NUL
个字节,但会为第二个代码块输出NUL
个输出字节,以便确认该问题的原因。
答案 2 :(得分:0)
您是否尝试过增加bufferSize。您应该看看在更改后nul开始插入的位置是否存在差异。
还不确定在遍历所有行的for循环到生成结果的单个方法之间发生了什么。你没有多个线程同时运行到这个文件吗?