StreamReader消耗的字节 [英] Bytes consumed by StreamReader
问题描述
有没有办法知道StreamReader使用了多少字节的流?
Is there a way to know how many bytes of a stream have been used by StreamReader?
我有一个项目,我们需要读取一个文件,该文件的文本标题为二进制数据的开头.我最初尝试读取此文件的过程是这样的:
I have a project where we need to read a file that has a text header followed by the start of the binary data. My initial attempt to read this file was something like this:
private int _dataOffset;
void ReadHeader(string path)
{
using (FileStream stream = File.OpenRead(path))
{
StreamReader textReader = new StreamReader(stream);
do
{
string line = textReader.ReadLine();
handleHeaderLine(line);
} while(line != "DATA") // Yes, they used "DATA" to mark the end of the header
_dataOffset = stream.Position;
}
}
private byte[] ReadDataFrame(string path, int frameNum)
{
using (FileStream stream = File.OpenRead(path))
{
stream.Seek(_dataOffset + frameNum * cbFrame, SeekOrigin.Begin);
byte[] data = new byte[cbFrame];
stream.Read(data, 0, cbFrame);
return data;
}
return null;
}
问题是,当我将 _dataOffset
设置为 stream.Position
时,我得到了StreamReader读取到的位置,而不是标题的末尾.我一想到它就很有意义,但是我仍然需要能够知道标头的末尾在哪里,而且我不确定是否有办法做到这一点,并且仍然可以利用StreamReader.
The problem is that when I set _dataOffset
to stream.Position
, I get the position that the StreamReader has read to, not the end of the header. As soon as I thought about it this made sense, but I still need to be able to know where the end of the header is and I'm not sure if there's a way to do it and still take advantage of StreamReader.
推荐答案
您可以通过多种方式找出 StreamReader
实际上返回了多少字节(与从流中读取相反).,恐怕它们都不是那么简单.
You can find out how many bytes the StreamReader
has actually returned (as opposed to read from the stream) in a number of ways, none of them too straightforward I'm afraid.
- 获取
textReader.CurrentEncoding.GetByteCount(totalLengthOfAllTextRead)
的结果,然后搜索流中的该位置. - 使用一些反射黑客来获取
StreamReader
对象的私有变量的值,该对象对应于内部缓冲区中的当前字节位置(与流中的当前字节位置不同-通常在后面,但没有当然不止等于).通过.NET Reflector判断,此变量似乎被命名为bytePos
. - 完全不用使用
StreamReader
,而是实现在Stream
或BinaryReader
之上构建的自定义ReadLine函数,即使(保证BinaryReader
绝不会超出您的要求.这个自定义函数必须逐个char从流中读取,因此您实际上必须使用低级的Decoder
对象(除非编码为ASCII/ANSI,在这种情况下事情会更简单一些)由于是单字节编码).
- Get the result of
textReader.CurrentEncoding.GetByteCount(totalLengthOfAllTextRead)
and then seek to this position in the stream. - Use some reflection hackery to retrieve the value of the private variable of the
StreamReader
object that corresponds to the current byte position within the internal buffer (different from that with the stream - usually behind, but no more than equal to of course). Judging by .NET Reflector, the this variable seems to be namedbytePos
. - Don't bother using a
StreamReader
at all but instead implement your custom ReadLine function built on top of theStream
orBinaryReader
even (BinaryReader
is guaranteed never to read further ahead than what you request). This custom function must read from the stream char by char, so you'd actually have to use the low-levelDecoder
object (unless the encoding is ASCII/ANSI, in which case things are a bit simpler due to single-byte encoding).
选项1将是我想象中效率最低的(因为您正在有效地重新编码刚解码的文本),选项3是最难实现的,尽管也许是最优雅的.我可能会建议您不要使用丑陋的反射技巧(选项2),尽管它看起来很诱人,它是最直接的解决方案,并且只用了几行.(说实话, StreamReader
类确实应该通过公共属性公开此变量,但是可惜没有.)因此,最终由您决定,但是方法1或3应该做得很好...
Option 1 is going to be the least efficient I would imagine (since you're effectively re-encoding text you just decoded), and option 3 the hardest to implement, though perhaps the most elegant. I'd probably recommend against using the ugly reflection hack (option 2), even though it's looks tempting, being the most direct solution and only taking a couple of lines. (To be quite honest, the StreamReader
class really ought to expose this variable via a public property, but alas it does not.) So in the end, it's up to you, but either method 1 or 3 should do the job nicely enough...
希望有帮助.
这篇关于StreamReader消耗的字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!