C# 为什么FileStream有时会忽略不可见的字符?

C# 为什么FileStream有时会忽略不可见的字符?,c#,filestream,C#,Filestream,我有两块代码,我试着用它们从C#中的文件流中读取数据。我在这里的总体目标是尝试将每一行文本读入一个字符串列表,但它们都被读入一个字符串(当同时使用读写访问打开时) 我注意到第一块代码正确读取了我所有的回车符和换行符,而另一块则忽略了它们。我不确定这里到底发生了什么。我用两种不同的方式打开了溪流,但这并不重要,对吧?无论如何,这里是第一段代码(正确读取我的空白字符): 更新2 再现问题的精确代码块(使用上面的文本作为文件)。在这种情况下,我实际上看到了问题,而没有尝试Open,只使用OpenRea

我有两块代码,我试着用它们从C#中的文件流中读取数据。我在这里的总体目标是尝试将每一行文本读入一个字符串列表,但它们都被读入一个字符串(当同时使用读写访问打开时)

我注意到第一块代码正确读取了我所有的回车符和换行符,而另一块则忽略了它们。我不确定这里到底发生了什么。我用两种不同的方式打开了溪流,但这并不重要,对吧?无论如何,这里是第一段代码(正确读取我的空白字符):

更新2

再现问题的精确代码块(使用上面的文本作为文件)。在这种情况下,我实际上看到了问题,而没有尝试
Open
,只使用
OpenRead

StreamReader sr = null;
StreamWriter sw = null;
FileStream fs = null;
List<string> content = new List<string>();
List<string> actual = new List<string>();
string line = string.Empty;

try
{
    // first, open up the file for reading/writing
    fs = File.OpenRead(path);
    sr = new StreamReader(fs);

    // read-in the entire file line-by-line
    while(!string.IsNullOrEmpty((line = sr.ReadLine())))
    {
        content.Add(line);
    }
    sr.Close();

    // now, erase the contents of the file
    File.WriteAllText(path, string.Empty);

    // make sure that the contents of the file have been erased
    fs = File.OpenRead(path);
    sr = new StreamReader(fs);
    if (!string.IsNullOrEmpty(line = sr.ReadLine()))
    {
        Trace.WriteLine("Failed: Could not erase the contents of the file.");
        Assert.Fail();
    }
    else
    {
        Trace.WriteLine("Passed: Successfully erased the contents of the file.");
    }

    // now, attempt to over-write the contents of the file
    fs.Close();
    fs = File.OpenWrite(path);
    sw = new StreamWriter(fs);
    foreach(var l in content)
    {
        sw.Write(l);
    }

    // read back the over-written contents of the file
    fs.Close();
    fs = File.OpenRead(path);
    sr = new StreamReader(fs);
    while (!string.IsNullOrEmpty((line = sr.ReadLine())))
    {
        actual.Add(line);
    }

    // make sure the contents of the file are correct
    if(content.SequenceEqual(actual))
    {
        Trace.WriteLine("Passed: The contents that were over-written are correct!");
    }
    else
    {
        Trace.WriteLine("Failed: The contents that were over-written are not correct!");
    }
}
finally
{
    // close out all the streams
    fs.Close();

    // finish-up with a message
    Trace.WriteLine("Finished running the overwrite-file test.");
}
StreamReader sr=null;
StreamWriter sw=null;
FileStream fs=null;
列表内容=新列表();
列表实际值=新列表();
string line=string.Empty;
尝试
{
//首先,打开文件进行读/写
fs=File.OpenRead(路径);
sr=新的StreamReader(fs);
//逐行读取整个文件
而(!string.IsNullOrEmpty((line=sr.ReadLine()))
{
内容。添加(行);
}
高级关闭();
//现在,删除文件的内容
File.writealText(路径,string.Empty);
//确保文件的内容已被删除
fs=File.OpenRead(路径);
sr=新的StreamReader(fs);
如果(!string.IsNullOrEmpty(line=sr.ReadLine()))
{
WriteLine(“失败:无法擦除文件的内容。”);
Assert.Fail();
}
其他的
{
WriteLine(“已通过:已成功擦除文件内容”);
}
//现在,尝试重写文件的内容
fs.Close();
fs=File.OpenWrite(路径);
sw=新StreamWriter(fs);
foreach(内容中的var l)
{
sw.Write(l);
}
//读回文件的重写内容
fs.Close();
fs=File.OpenRead(路径);
sr=新的StreamReader(fs);
而(!string.IsNullOrEmpty((line=sr.ReadLine()))
{
实际。添加(行);
}
//确保文件的内容正确无误
if(内容顺序相等(实际))
{
WriteLine(“已通过:重写的内容是正确的!”);
}
其他的
{
Trace.WriteLine(“失败:重写的内容不正确!”);
}
}
最后
{
//封锁所有的溪流
fs.Close();
//以留言结束
WriteLine(“已完成覆盖文件测试的运行”);
}

由生成的新文件

foreach(var l in content)
{
    sw.Write(l);
}
不包含行尾字符,因为
内容中不包含行尾字符

正如@DaveKidder在中指出的那样,特别指出生成的行不包括行的末尾

当你这样做的时候

while(!string.IsNullOrEmpty((line = sr.ReadLine())))
{
    content.Add(line);
}
sr.Close();

您正在丢失行尾字符。

FileStream不会忽略“不可见”字符,它不关心字符
StreamReader
是一个读取文本和处理换行符的类,但它也不会忽略它们。两种情况下的文件是否相同?内容是一样的吗?你能发布重现这个问题的代码吗?@PanagiotisKanavos显然我肯定有X-Y问题。是的,我当然可以,谢谢你的邀请。希望这将有助于了解这里发生了什么。我无法在Windows上的.NET 4.6.2上重现此代码的问题。正如人们所料,这两段代码在第一个空行之前都会单独产生行,因为
File.Open
File.OpenRead
都是围绕
FileStream
构造函数的简单包装。4.5和4.6.2都没有这样的问题。这是人们已经注意到的基本操作
FileStream
根本不处理字符,它只返回字节。是StreamReader将字节解释为字符。最有可能的是,内容不一样,可能是因为写入文件的流保持打开状态?您没有指定
编码,因此默认为UTF-8。你确定文件是UTF-8格式的吗?如果是国家非ASCII代码页,ASCII范围之外的字符可能会被解释为多字节字符,这将破坏一切。在读取文本文件时使用正确的编码。我第二次尝试读取它,这是正确的,但我第一次在示例中读取它,它是有效的。@StevieV您第一次读取它时,在第15行到第17行,您正在读取在应用程序之外使用行尾符号创建的文件。第二次读取时,从第50行到第53行,您正在读取应用程序创建的没有行尾符号的文件。这与读取方法无关,第一次读取数据1时,第二次读取数据2时,数据1与数据2具有不同的字节。在第11行之后,您可以存储字节数组,然后在第48行之后执行相同的操作并检查它们,它们将是不同的字节集。
StreamReader sr = null;
StreamWriter sw = null;
FileStream fs = null;
List<string> content = new List<string>();
List<string> actual = new List<string>();
string line = string.Empty;

try
{
    // first, open up the file for reading/writing
    fs = File.OpenRead(path);
    sr = new StreamReader(fs);

    // read-in the entire file line-by-line
    while(!string.IsNullOrEmpty((line = sr.ReadLine())))
    {
        content.Add(line);
    }
    sr.Close();

    // now, erase the contents of the file
    File.WriteAllText(path, string.Empty);

    // make sure that the contents of the file have been erased
    fs = File.OpenRead(path);
    sr = new StreamReader(fs);
    if (!string.IsNullOrEmpty(line = sr.ReadLine()))
    {
        Trace.WriteLine("Failed: Could not erase the contents of the file.");
        Assert.Fail();
    }
    else
    {
        Trace.WriteLine("Passed: Successfully erased the contents of the file.");
    }

    // now, attempt to over-write the contents of the file
    fs.Close();
    fs = File.OpenWrite(path);
    sw = new StreamWriter(fs);
    foreach(var l in content)
    {
        sw.Write(l);
    }

    // read back the over-written contents of the file
    fs.Close();
    fs = File.OpenRead(path);
    sr = new StreamReader(fs);
    while (!string.IsNullOrEmpty((line = sr.ReadLine())))
    {
        actual.Add(line);
    }

    // make sure the contents of the file are correct
    if(content.SequenceEqual(actual))
    {
        Trace.WriteLine("Passed: The contents that were over-written are correct!");
    }
    else
    {
        Trace.WriteLine("Failed: The contents that were over-written are not correct!");
    }
}
finally
{
    // close out all the streams
    fs.Close();

    // finish-up with a message
    Trace.WriteLine("Finished running the overwrite-file test.");
}
foreach(var l in content)
{
    sw.Write(l);
}
while(!string.IsNullOrEmpty((line = sr.ReadLine())))
{
    content.Add(line);
}
sr.Close();