C# TextReader.ReadLine返回不完整的行
我正在使用C# TextReader.ReadLine返回不完整的行,c#,networking,C#,Networking,我正在使用套接字通过TCP接收数据,并使用文本阅读器.ReadLine从连接中读取行。未收到完整行时出现问题--TextReader.ReadLine返回不完整的字符串。我希望它返回null,表示无法读取整行。我该怎么做 基本上,我收到了以下数据: "hello\nworld\nthis is a test\n" 当我运行ReadLine时,我会得到以下结果: "hello" "world" "this is a te" <null> <socket gets more da
套接字
通过TCP接收数据,并使用文本阅读器.ReadLine
从连接中读取行。未收到完整行时出现问题--TextReader.ReadLine
返回不完整的字符串。我希望它返回null
,表示无法读取整行。我该怎么做
基本上,我收到了以下数据:
"hello\nworld\nthis is a test\n"
当我运行ReadLine
时,我会得到以下结果:
"hello"
"world"
"this is a te"
<null>
<socket gets more data>
"st"
<null>
谢谢。听起来数据是用一些额外的分隔符发送的。假设您在网络流上使用StreamReader,它的行为应该完全符合您的预期。我建议您使用Wireshark查看套接字接收到的确切数据 我还怀疑它是否返回null,然后返回另一行-您确定这不是指它返回空字符串,然后返回另一行吗 编辑:现在你已经发布了代码,原因更清楚了——你一次只解码一个缓冲区。这真的行不通,可能会以更严重的方式破坏。缓冲区甚至可能不会在字符边界处中断 老实说,同步阅读和使用
StreamReader
会容易得多。异步执行时,应该使用System.Text.Decoder
,如果需要,它可以存储任何以前的状态(从上一个缓冲区的末尾开始)。您还必须存储前一行的读取量-我怀疑您根本无法使用TextReader
,或者至少您必须对最后一个字符为'\r'或'\n'的情况进行特殊处理。请记住,一个缓冲区可以以“\r”结尾,下一个缓冲区可以以“\n”开头,表示它们之间的一个换行符。看看有多困难
你真的,真的需要异步处理吗
编辑:听起来您可以处理一些基本上可以将数据转储到其中并附加“LineCompleted”事件处理程序的事情。您可以先附加事件处理程序,然后继续将数据转储到事件处理程序中,直到没有更多数据为止(此时您需要告诉事件处理程序数据已经完成)。如果这听起来合适的话,我可能会尝试为MiscUtil开发这样一个类——但我不太可能在下周内完成它(我现在真的很忙)。听起来数据是用一些额外的分隔符发送的。假设您在网络流上使用StreamReader,它的行为应该完全符合您的预期。我建议您使用Wireshark查看套接字接收到的确切数据 我还怀疑它是否返回null,然后返回另一行-您确定这不是指它返回空字符串,然后返回另一行吗 编辑:现在你已经发布了代码,原因更清楚了——你一次只解码一个缓冲区。这真的行不通,可能会以更严重的方式破坏。缓冲区甚至可能不会在字符边界处中断 老实说,同步阅读和使用
StreamReader
会容易得多。异步执行时,应该使用System.Text.Decoder
,如果需要,它可以存储任何以前的状态(从上一个缓冲区的末尾开始)。您还必须存储前一行的读取量-我怀疑您根本无法使用TextReader
,或者至少您必须对最后一个字符为'\r'或'\n'的情况进行特殊处理。请记住,一个缓冲区可以以“\r”结尾,下一个缓冲区可以以“\n”开头,表示它们之间的一个换行符。看看有多困难
你真的,真的需要异步处理吗
编辑:听起来您可以处理一些基本上可以将数据转储到其中并附加“LineCompleted”事件处理程序的事情。您可以先附加事件处理程序,然后继续将数据转储到事件处理程序中,直到没有更多数据为止(此时您需要告诉事件处理程序数据已经完成)。如果这听起来合适的话,我可能会尝试为MiscUtil编写这样一个类,但我不太可能在下周内完成它(我现在真的很忙)。有一个缓冲区(开始为空),每次阅读时
- 如果缓冲区中有\n,请删除所有内容 所有的东西,包括它和返回它
- 尽可能地读取,并将读取的内容附加到缓冲区中
- 如果由于eof导致读取失败,则返回并清除内容,除非缓冲区为空,在这种情况下,释放eof
- 如果您阅读的内容中有\n错误,请从顶部重试, 否则返回空值
- 如果缓冲区中有\n,请删除所有内容 所有的东西,包括它和返回它
- 尽可能地读取,并将读取的内容附加到缓冲区中
- 如果由于eof导致读取失败,则返回并清除内容,除非缓冲区为空,在这种情况下,释放eof
- 如果您阅读的内容中有\n错误,请从顶部重试, 否则返回空值
--MarkusQ查看我对一个问题的答案。它以类似流的方式涉及异步套接字I/O和读取行。希望这能有所帮助。看看我对一个问题的答案。它以类似流的方式涉及异步套接字I/O和读取行。希望能有所帮助。这里可以看到几个问题:
var endPoint = ...;
var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
socket.Connect(endPoint);
var stream = new NetworkStream(socket, true);
var messageBuffer = new StringBuilder();
// Data received async callback (called several times).
int bytesRead = stream.EndRead(result);
string data = Encoding.UTF8.GetString(readBuffer.Take(bytesRead).ToArray());
messageBuffer.Append(data);
using(var reader = new StringReader(messageBuffer.ToString()))
{
// This loop does not know that Message.Read reads lines. For all it knows, it could read bytes or words or the whole stream.
while((Message msg = Message.Read(reader)) != null) // See below.
{
Console.WriteLine(msg.ToString()); // See example input/echo above.
}
messageBuffer = new StringBuilder(reader.ReadToEnd());
}
// Method of Message.
public static Message Read(TextReader reader)
{
string line = reader.ReadLine();
if(line == null)
return null;
return Message.FromRawString(line);
}
// Async callback.
Message message;
while((message = Message.ReadBytes(messageBuffer)) != null)
{
OnMessageReceived(new MessageEventArgs(message));
}
// Message class.
public static Message ReadBytes(List<byte> data)
{
int end = data.FindIndex(b => b == '\n' || b == '\r');
if(end == -1)
return null;
string line = Encoding.UTF8.GetString(data.Take(end).ToArray());
data.RemoveRange(0, end + 1);
if(line == "")
return ReadBytes(data);
if(line == null)
return null;
return Message.FromRawString(line);
}