我想使用两个不同的编写器来处理一种“混合格式”文件(这个问题与我之前关于如何编写这种文件的问题有关:使用两个“using”语句和两个编写器写入同一个文件)
我的问题是,当我打开一个文件然后创建一个StreamReader
来读取它时,我在该文件上创建的每个其他读取器都会得到一个空流并且无法读取任何内容。
最小示例如下。假设我们有一个文件包含两行,第一句是“saying” first line
,第二句是“saying” second line
。
然后,写入以下内容:
using (FileStream file = new(fileName, FileMode.Open, FileAccess.Read))
{
List<string> strings = new();
using (StreamReader reader = new StreamReader(file, leaveOpen: true))
{
strings.Add(reader.ReadLine());
}
using (StreamReader reader = new StreamReader(file, leaveOpen: true))
{
strings.Add(reader.ReadLine());
}
}
我希望列表strings
包含元素"first line"
和"second line"
。相反,当我运行代码时,我得到了第一个元素"first line"
,但的第二个元素strings
是null
。我显然不明白这里的某些东西,但我不知道是什么。
StreamReader
每次会读取一大块文件(否则它必须逐个字符地读取才能找到行尾,这效率太低了)。因此,您不能指望它在任何特定点离开 FileStream 的位置。OP 已澄清他们正在读取NRRD 格式的数据。这包括标题列表,由两个换行符与二进制数据分隔:
(这类似于读取 HTTP 标头,然后读取正文)。
读取此内容的最简单方法可能是扫描整个文件,寻找相邻的两个换行符。请记住,NRRD 中的换行符可以是 LF 和 CRLF。
一旦找到该位置,就可以将文件的第一部分读取为文本,然后返回二进制数据的开头,将其余部分读取为二进制。不幸的是,这会有点冗长,但不幸的是,这可能是不可避免的。
或者,类似下面的方法似乎有效。它使用 来
StreamReader
处理确定换行符(LF 与 CRLF 等)的复杂工作,但通过给它一个MemoryStream
读取来限制它,我们每次只向其添加一个字节。由于
StreamReader.ReadLine
在到达流末尾时(以及读到换行符时)会返回一行,我们还必须检查StreamReader.EndOfStream
。在此在线运行。
另一种方法是将其包装
FileStream
在另一个流中,从而人为地限制可以读取的字节数。以下示例非常不完整,但确实可以完成此处的工作:这样你就可以写出类似这样的内容:
在此在线运行。