#c# #.net-3.5 #stream
#c# #.net-3.5 #поток
Вопрос:
Я работаю с подключением к сокету — чтобы упростить задачу, я получаю NetworkStream сокета и оборачиваю его в StreamReader, что упрощает работу с преимущественно текстовым содержимым, которое мой сокет получает с сервера.
Однако бывают случаи, когда сервер отправляет двоичную информацию, например:
TEXT
MORETEXT
500 BYTES OF BINARY DATA FOLLOWS THIS LINE
{500 bytes of binary data}
Я отлично считываю текстовое содержимое с помощью StreamReader, но поскольку StreamReader имеет свой собственный буфер, это означает, что StreamReader захватывает двоичные данные до того, как я смогу переключиться на BinaryReader для чтения 500 байт двоичных данных.
Есть ли способ обойти это? Я хотел бы иметь возможность читать текстовые данные, сохраняя при этом возможность чтения двоичных данных.
Комментарии:
1. Я использую C # в .NET 3.5, FWIW.
Ответ №1:
Мне следует провести свое исследование получше; оказывается, что класс BinaryReader уже содержит методы обработки строк и символов (хотя ему нужно несколько, например ReadLine, которые можно легко добавить, создав его подкласс).
Тогда странно, почему BinaryReader не создает подкласс TextReader, поскольку он более чем способен.
Ответ №2:
Вот расширение BinaryReader, которое вы можете использовать для выполнения ReadLine и обычных функций BinaryReader.
public class LineReader : BinaryReader
{
private Encoding _encoding;
private Decoder _decoder;
const int bufferSize = 1024;
private char[] _LineBuffer = new char[bufferSize];
public LineReader(Stream stream, int bufferSize, Encoding encoding)
: base(stream, encoding)
{
this._encoding = encoding;
this._decoder = encoding.GetDecoder();
}
public string ReadLine()
{
int pos = 0;
char[] buf = new char[2];
StringBuilder stringBuffer = null;
bool lineEndFound = false;
while(base.Read(buf, 0, 2) > 0)
{
if (buf[1] == 'r')
{
// grab buf[0]
this._LineBuffer[pos ] = buf[0];
// get the 'n'
char ch = base.ReadChar();
Debug.Assert(ch == 'n');
lineEndFound = true;
}
else if (buf[0] == 'r')
{
lineEndFound = true;
}
else
{
this._LineBuffer[pos] = buf[0];
this._LineBuffer[pos 1] = buf[1];
pos = 2;
if (pos >= bufferSize)
{
stringBuffer = new StringBuilder(bufferSize 80);
stringBuffer.Append(this._LineBuffer, 0, bufferSize);
pos = 0;
}
}
if (lineEndFound)
{
if (stringBuffer == null)
{
if (pos > 0)
return new string(this._LineBuffer, 0, pos);
else
return string.Empty;
}
else
{
if (pos > 0)
stringBuffer.Append(this._LineBuffer, 0, pos);
return stringBuffer.ToString();
}
}
}
if (stringBuffer != null)
{
if (pos > 0)
stringBuffer.Append(this._LineBuffer, 0, pos);
return stringBuffer.ToString();
}
else
{
if (pos > 0)
return new string(this._LineBuffer, 0, pos);
else
return null;
}
}
}