使用两个“using”语句和两个读取器从同一文件中读取数据

问题描述 投票:0回答:1

我想使用两个不同的编写器处理一种“混合格式”文件(这个问题与我之前关于如何编写此类文件的问题相关:使用两个“using”语句和两个编写器写入同一个文件 )

我的问题是,当我打开一个文件,然后创建一个

StreamReader
来读取它时,我在该文件上创建的每个其他读取器都会获得一个空流,并且无法读取任何内容。

最小示例如下。假设我们有一个包含两行的文件,第一行说

first line
,第二行说
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
。 我显然不明白这里的一些东西,但我不知道是什么。

c# streamreader
1个回答
1
投票

StreamReader
将一次读取文件的一大块(否则它必须逐个字符地读取才能找到行结尾,这将是非常低效的)。因此,您不能依赖它在任何特定点留下 FileStream 的位置。

OP 已澄清他们正在读取NRRD 格式的数据。这包含一个标头列表,通过两个换行符与二进制数据分隔:

NRRD000X
<field>: <desc>
<field>: <desc>
# <comment>
...
<field>: <desc>
<key>:=<value>
<key>:=<value>
<key>:=<value>
# <comment>

<data><data><data><data><data><data>...

(这类似于读取 HTTP 标头,然后读取正文)。

阅读此内容的最简单方法是可能扫描文件,查找彼此相邻的两个换行符。请记住,NRRD 中的换行符可以是 LF 和 CRLF。

一旦获得该位置,您可以将文件的第一部分作为文本读取,然后返回到二进制数据的开头并将其余部分作为二进制读取。不幸的是,这会有点啰嗦,但不幸的是,这可能是不可避免的。


或者,像下面这样的东西似乎也有效。这使用

StreamReader
来处理计算换行符是什么的混乱事务(LF 与 CRLF 等),但通过给它一个
MemoryStream
来读取来限制它,我们一次只添加一个字节。

由于

StreamReader.ReadLine
返回以 EOF 和换行符结尾的行,我们还必须检查
StreamReader.EndOfStream
来告诉我们它是否读取了已到达输入末尾的行。

byte[] b = new byte[1];
int bufferPosition = 0;
while (true)
{
    int bytesRead = file.Read(b, 0, b.Length);
    if (bytesRead == 0)
    {
        // We ran out of file data before reaching the end of the headers
        break;
    }

    buffer.Write(b, 0, b.Length);
    buffer.Position = bufferPosition;

    reader.DiscardBufferedData();
    string? line = reader.ReadLine();
    if (line != null && !reader.EndOfStream)
    {
        Console.WriteLine(line);
        bufferPosition = (int)buffer.Length - 1;
        if (reader.ReadLine() == "")
        {
            break;
        }
    }
}

在此处在线运行它

© www.soinside.com 2019 - 2024. All rights reserved.