问题BinaryReader.ReadChars()
-
05-07-2019 - |
题
我碰到什么我认为是一个问题与BinaryReader.ReadChars()方法。当我裹BinaryReader周围的一个原座NetworkStream偶尔我得到一流的腐败,那里的流正在读取得同步。流问题包含的信息中的二进制序列化协议。
我已经追踪这个倒下
- 它只发生在阅读unicode string(编码使用的编码。BigEndian)
- 它只发生当串在的问题是分裂的两个tcp分组(确认使用查看)
我觉得什么是发生是以下(在下文的例子下面)
- BinaryReader.ReadChars()称为要求它读3个字符的(string长度编码之前的串本身)
- 第一环境内的请求,一读的6个字节(3剩下的符*2个字节/char)关于流网络
- 网络流中只有3个字节提供
- 3字节读到当地的缓冲区
- 缓冲区交给解码器
- 解码1char,并保持其它字节在它自己内部缓冲区
- 第二循环内部的请求,一读的4个字节!(2剩余的符*2个字节/char)
- 网络流的所有4个字节提供
- 4字节读到当地的缓冲区
- 缓冲区交给解码器
- 解码2炭的,让剩余的4个字节的内部
- 串解码完成
电子监管的代码试图解组的下一个项目,并嘎嘎因为流腐败。
char[] buffer = new char[3]; int charIndex = 0; Decoder decoder = Encoding.BigEndianUnicode.GetDecoder(); // pretend 3 of the 6 bytes arrives in one packet byte[] b1 = new byte[] { 0, 83, 0 }; int charsRead = decoder.GetChars(b1, 0, 3, buffer, charIndex); charIndex += charsRead; // pretend the remaining 3 bytes plus a final byte, for something unrelated, // arrive next byte[] b2 = new byte[] { 71, 0, 114, 3 }; charsRead = decoder.GetChars(b2, 0, 4, buffer, charIndex); charIndex += charsRead;
我觉得根本是错误的。净码,它使用charsRemaining*字节/char每个循环计算剩余的字节的需要。因为额外字节隐藏在解码器这种计算可以通过一项引起额外字节到被消耗掉输入流。
这里的.净框架中的代码问题
while (charsRemaining>0) {
// We really want to know what the minimum number of bytes per char
// is for our encoding. Otherwise for UnicodeEncoding we'd have to
// do ~1+log(n) reads to read n characters.
numBytes = charsRemaining;
if (m_2BytesPerChar)
numBytes <<= 1;
numBytes = m_stream.Read(m_charBytes, 0, numBytes);
if (numBytes==0) {
return (count - charsRemaining);
}
charsRead = m_decoder.GetChars(m_charBytes, 0, numBytes, buffer, index);
charsRemaining -= charsRead;
index+=charsRead;
}
我不完全确定这是否是一个错误,或者只是一个滥用API。工作圆此问题我只是字节计算需要我自己,阅读他们,然后运行的字节[]通过相关的编码。形式().但是,这不起作用的东西喜欢UTF-8。
有兴趣听到人的思想在这和我是否做错了什么或没有。也许它会保存下来的人几个小时/天的繁琐的调试。
编辑:发布连接 连接跟踪项目
解决方案
我已经转载的问题,你提到的 BinaryReader.ReadChars
.
虽然开发总是需要考虑预期的时候撰写的东西喜欢流和解码器,这似乎是一个相当重大的错误 BinaryReader
因为这类目的是用于读取的数据结构由各种类型的数据。在这种情况下,我同意 ReadChars
应该保守什么阅读,以避免失去这些字节。
没有什么错你的解决方法的使用 Decoder
直接的,毕竟这是什么 ReadChars
不的幕后。
Unicode是一种简单的情况。如果你认为有关任意编码,真的没有通用的方法,以确保正确的数字节的消耗当你传递一个字符数,而不是一个数字节(认为关于不同长度的人物和情况下,涉及格式错误输入)。由于这个原因,避免 BinaryReader.ReadChars
在有利于阅读的具体数字节提供了一个更强大的,一般的解决方案。
我会建议你把这个给了微软的注意通过 http://connect.microsoft.com/visualstudio.
其他提示
有趣;你可以报告这种关于"连接"。作为停止差距,你也可以试试绕与 BufferredStream
, 但我希望这是掩盖了一个裂缝(它仍然可能发生,但是不太频繁).
其他的方法,当然,是预缓冲区的整个消息(但不是整个流);然后读喜欢的东西 MemoryStream
-假定网络协议 已 逻辑(和地区长-前缀的,并没有太大)的消息。然后,当它是 解码 所有的数据可用。
这让我想起了我自己的一个问题(读一HttpResponseStream失败)在那里我有一个问题,阅读时从HTTP响应流StreamReader会认为,它击中了结束流过早所以我的分析程序就会弹出人意料。
像马克建议对于您的问题我第一次尝试的预在缓冲 MemoryStream
效果很好,而是意味着你可能需要等待很长一段时间,如果你有一个大型文件的读取(特别是从网络/网)之前你可以做任何有用的。我最终解决创造我自己扩展的位置其复盖的阅读方法,并限定他们使用的读出数据块方法(这不会阻止阅读即它等待,直到它可以获得确切数字你问)
你的问题可能是由像我这样的事实,即读取的方法不保证返回的数字,你要求,例如如果你在看的文件 BinaryReader.Read
(http://msdn.microsoft.com/en-us/library/ms143295.aspx)方法你会看到它国家:
回值
类型:系统..::.Int32
数字符读入缓冲区。这可能低于该数字节的要求,如果许多字节不适用,或者,它可能为零,如果流结束为止。
由于BinaryReader有没有读出数据块方法像一个位置你能做的就是把你自己的方式监测该位置的自己或Marc的预缓存。
我的工作与Unity3D/单atm和ReadChars的方法可能甚至含有较多的错误。我做了一串这样的:
mat.name = new string(binaryReader.ReadChars(64));
mat.name
甚至包含正确的string,但我可能只是增添的字符串 之前 它。一切后串只是disappered.甚至串。格式。我的解决方案迄今为止没有使用ReadChars的方法,但是读取的数据作为字阵列,并将其转换为string:
byte[] str = binaryReader.ReadBytes(64);
int lengthOfStr = Array.IndexOf(str, (byte)0); // e.g. 4 for "clip\0"
mat.name = System.Text.ASCIIEncoding.Default.GetString(str, 0, lengthOfStr);