问题描述
我有一个用于 RTSP 通信的 TCP 套接字.由于数据是基于行的文本数据和字节大小的块的混合,我将 StreamReader
附加到 tcpClient.GetStream()
,并调用 .ReadLine()
文本数据需要时.
I have a TCP socket that I use for RTSP communication.As the data is a mixture of line based textual data and byte sized blocks, I attached a StreamReader
to the tcpClient.GetStream()
, and call .ReadLine()
whenever needed for the textual data.
当我需要读取响应正文时,我有一个固定的字节数,所以我尝试使用 stream.Read()
但它会阻塞,大概是 StreamReader
有已经将数据读入自己的缓冲区.与字符编码一样,它只读取固定数量的字符而不是字节.
When I need to read a response body, I have a fixed byte count so I tried using stream.Read()
but that blocks, presumably as the StreamReader
has already read the data into its own buffer. As that does character encoding, it only reads a fixed number of characters rather than bytes.
有什么方法可以从流中读取固定数量的字节而不完全废弃 StreamReader
或希望二进制数据/内容是 7 位安全的(反过来又不会解码为 UTF-8)?另一种方法是将 StreamReader
的编码设置为 ASCII
,但这可能会破坏被定义为 UTF-8 的其余协议.
Is there any way I can read a fixed number of bytes from the stream without scrapping the StreamReader
altogether or hoping that the binary data/content is 7-bit safe (and in turn won't decode as UTF-8)?An alternative is to set the StreamReader
's encoding to ASCII
but that potentially breaks the rest of the protocol which is defined as UTF-8.
设置:
this.rtspStream = this.rtspSocket.GetStream();
this.rtspReader = new StreamReader(this.rtspStream, Encoding.UTF8);
文字阅读:
string line;
while ((line = this.rtspReader.ReadLine()) != string.Empty) {
// ...
}
二进制读取:
byte[] responseBody = new byte[contentLength];
this.rtspStream.Read(responseBody, 0, contentLength);
推荐答案
查看 StreamReader 源,不可能混合使用 StreamReader
和直接从流读取字节,因为 StreamReader
将字节读入然后它的内部缓冲区将它所能解码的所有内容都解码为一个可供读取的字符缓冲区.
Looking at the StreamReader source, it is not possible to mix the use of the StreamReader
and reading of bytes direct from the stream as the StreamReader
reads bytes into its internal buffer then decodes all it can into a character buffer available for reading.
将缓冲区大小设置为 0 无济于事,因为它强制将缓冲区大小设置为至少 128 字节.
Setting the buffer size to 0 doesn't help as it forces this to a minimum of 128 bytes.
为了我的使用,我需要完全废弃 StreamReader
并将 ReadLine()
替换为可以直接从流中读取以进行解析的内容.
For my use, I needed to scrap the StreamReader
altogether and replace the ReadLine()
with something that will read directly from the stream for parsing myself.
private string ReadLine() {
// Stringbuilder to insert the read characters in to
StringBuilder line = new StringBuilder();
// Create an array to store the maximum number of bytes for a single character
byte[] bytes = new byte[this.encoding.GetMaxByteCount(1)];
int byteCount = 0;
while (true) {
// Read the first byte
bytes[0] = (byte)this.rtspStream.ReadByte();
byteCount = 1;
// If the encoding says this isn't a full character, read until it does
while (this.encoding.GetCharCount(bytes, 0, byteCount) == 0) {
bytes[byteCount++] = (byte)this.rtspStream.ReadByte();
}
// Get the unencoded character
char thisChar = this.encoding.GetChars(bytes, 0, byteCount)[0];
// Exit if it's a new line (/r/n or /n)
if (thisChar == '\r') { continue; }
if (thisChar == '\n') { break; }
line.Append(thisChar);
}
return line.ToString();
}
这篇关于混合 StreamReader.Read... 和 Stream.Read的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!