字符串未正确添加到自身。但是能够比较
String is not adding to itself properly. But is able to compare
string returndata = "";
string FullResponce = "";
bool RecieveAgain = true;
while (RecieveAgain == true)
{
byte[] inStream = new byte[clientSocket.ReceiveBufferSize];
serverStream.Read(inStream, 0, inStream.Length);
returndata = System.Text.Encoding.ASCII.GetString(inStream);
FullResponce += returndata;
if (FullResponce.Contains("< /Program>"))
{
RecieveAgain = false;
}
}
xmlDoc.LoadXml(FullResponce);
这是一个继续检索数据的循环,直到结束 xml 块 ("< /Program>"
) 包含在所有已发送数据包组合的 FullResponce 中。当代码为 运行 时,在我的例子中经过大约 5 个循环,("< /Program>"
) 最终包含在文本中。
因此 if 语句 运行s 最终使 RecieveAgain = false,从而打破循环,因此 FullResponce 可以加载到 xml 中。当它试图加载 xml 时,它给我一个 xml 不完整的错误,当我检查 FullResponce 文本时,它似乎丢失了第一个数据包以外的所有内容(甚至遗漏了"< /Program>"
,这很奇怪,因为循环中的 if 语句检测到了它)。
因为少了一半xml,所以报错了,但是为什么Full Responce没有正确地加到自己身上呢?代码 FullResponce += returndata 似乎只有 运行 一次,仅此而已。
还需要注意的另一件事是,当我在此循环的开头设置断点并手动遍历所有代码直到它尝试加载到 xml 时,它工作得很好,并且FullResponce 字符串已满且包含所有正确数据。
就像我在程序运行一步一步的时候,能够正确的把returndata加入到FullResponce中,但是当没有断点,正常调试的时候,就报错了。
这是怎么回事,我该如何解决?
你的代码有很多问题,但最大的一个(也是导致你问题的那个)是你没有考虑到接收到的实际字节数.这会导致字符串中存在空字符,然后 some 组件会将其解释为字符串的结尾。 (计算 .NET 字符串,不以空字符结尾,但仍然有很多代码不希望字符串中间出现空字符)。
您应该将循环更改为更像这样:
StringBuilder fullResponse = new StringBuilder();
byte[] buffer = new byte[clientSocket.ReceiveBufferSize];
int bytesRead;
while ((bytesRead = serverStream.Read(buffer, 0, buffer.Length)) > 0)
{
string textRead = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead);
fullResponse.Append(textRead);
}
xmlDoc.LoadXml(fullResponse.ToString());
注意:除了空字符的问题外,上述版本还修复了原始情况中的另一个问题,即您在循环中使用字符串连接。这样做会导致严重的性能和内存消耗问题;使用 StringBuilder
是在循环中连接文本的合适方法。
注意:只要你确定你的XML只有ASCII字符,以上就可以了。但请注意,UTF8 和 UTF16 现在很常见,XML 在技术上是其中一种格式,并且有很多 XML 里面有非 ASCII 字符。您可能需要仔细检查 XML 的编码并确保您在此处使用正确的编码。
注意:在上面的代码中,它使用流结束指示(即读取操作returns字节数为0)来终止环形。无论如何,您绝对应该检查一下。并且 StringBuilder
无法检查是否包含某些特定文本,因此您之前的方法与 StringBuilder
.
的使用不兼容
现在,您可能在想自己 "hey, but there might be more data! why not just accept the performance hit and use string concatenation with Contains()
?"。好吧,答案是:如果在 XML 结束后可能存在更多数据,那么您需要一种比寻找 XML 结束更可靠的方法来检测 XML关闭标签。
一个 Stream
对象无法知道它应该在 XML 结束时停止读取您的数据,因此最后一个读取操作 — [=62= 的那个] 的最终关闭标记 — 可以(并且可能会)包含 XML.
之后的一部分数据
这意味着你会遇到两个问题:
- 您的 XML 被额外数据污染了
- 额外的数据(可能对以后发生的事情很重要)已经被读取,需要它的代码将无法使用。
解决此问题的一种方法是在数据流中的 XML 之前加上字节数,以便您的循环知道在停止之前要读取多少字节。另一种方法可能是将 XML 转换为二进制,然后转换为 base64(可能首先压缩二进制),然后使用您知道的某些字符分隔 base64 数据对 base64 数据无效(例如 space、换行符、制表符等)。
无论您如何处理它,您都会通过 XML 本身的最终关闭标记以外的某种机制知道 XML 的结尾,因此仍然可以使用 StringBuilder
并且不必在字符串中搜索该结束标记。
我会提供有关后者的更多详细信息,但您没有在问题中提供足够的信息来这样做。如果您需要这方面的具体帮助,请 post 提出一个新问题并确保提供适当的详细信息。有关如何更好地提出问题的建议,请参阅 https://whosebug.com/help/mcve and https://whosebug.com/help/how-to-ask。
string returndata = "";
string FullResponce = "";
bool RecieveAgain = true;
while (RecieveAgain == true)
{
byte[] inStream = new byte[clientSocket.ReceiveBufferSize];
serverStream.Read(inStream, 0, inStream.Length);
returndata = System.Text.Encoding.ASCII.GetString(inStream);
FullResponce += returndata;
if (FullResponce.Contains("< /Program>"))
{
RecieveAgain = false;
}
}
xmlDoc.LoadXml(FullResponce);
这是一个继续检索数据的循环,直到结束 xml 块 ("< /Program>"
) 包含在所有已发送数据包组合的 FullResponce 中。当代码为 运行 时,在我的例子中经过大约 5 个循环,("< /Program>"
) 最终包含在文本中。
因此 if 语句 运行s 最终使 RecieveAgain = false,从而打破循环,因此 FullResponce 可以加载到 xml 中。当它试图加载 xml 时,它给我一个 xml 不完整的错误,当我检查 FullResponce 文本时,它似乎丢失了第一个数据包以外的所有内容(甚至遗漏了"< /Program>"
,这很奇怪,因为循环中的 if 语句检测到了它)。
因为少了一半xml,所以报错了,但是为什么Full Responce没有正确地加到自己身上呢?代码 FullResponce += returndata 似乎只有 运行 一次,仅此而已。
还需要注意的另一件事是,当我在此循环的开头设置断点并手动遍历所有代码直到它尝试加载到 xml 时,它工作得很好,并且FullResponce 字符串已满且包含所有正确数据。
就像我在程序运行一步一步的时候,能够正确的把returndata加入到FullResponce中,但是当没有断点,正常调试的时候,就报错了。
这是怎么回事,我该如何解决?
你的代码有很多问题,但最大的一个(也是导致你问题的那个)是你没有考虑到接收到的实际字节数.这会导致字符串中存在空字符,然后 some 组件会将其解释为字符串的结尾。 (计算 .NET 字符串,不以空字符结尾,但仍然有很多代码不希望字符串中间出现空字符)。
您应该将循环更改为更像这样:
StringBuilder fullResponse = new StringBuilder();
byte[] buffer = new byte[clientSocket.ReceiveBufferSize];
int bytesRead;
while ((bytesRead = serverStream.Read(buffer, 0, buffer.Length)) > 0)
{
string textRead = System.Text.Encoding.ASCII.GetString(buffer, 0, bytesRead);
fullResponse.Append(textRead);
}
xmlDoc.LoadXml(fullResponse.ToString());
注意:除了空字符的问题外,上述版本还修复了原始情况中的另一个问题,即您在循环中使用字符串连接。这样做会导致严重的性能和内存消耗问题;使用 StringBuilder
是在循环中连接文本的合适方法。
注意:只要你确定你的XML只有ASCII字符,以上就可以了。但请注意,UTF8 和 UTF16 现在很常见,XML 在技术上是其中一种格式,并且有很多 XML 里面有非 ASCII 字符。您可能需要仔细检查 XML 的编码并确保您在此处使用正确的编码。
注意:在上面的代码中,它使用流结束指示(即读取操作returns字节数为0)来终止环形。无论如何,您绝对应该检查一下。并且 StringBuilder
无法检查是否包含某些特定文本,因此您之前的方法与 StringBuilder
.
现在,您可能在想自己 "hey, but there might be more data! why not just accept the performance hit and use string concatenation with Contains()
?"。好吧,答案是:如果在 XML 结束后可能存在更多数据,那么您需要一种比寻找 XML 结束更可靠的方法来检测 XML关闭标签。
一个 Stream
对象无法知道它应该在 XML 结束时停止读取您的数据,因此最后一个读取操作 — [=62= 的那个] 的最终关闭标记 — 可以(并且可能会)包含 XML.
这意味着你会遇到两个问题:
- 您的 XML 被额外数据污染了
- 额外的数据(可能对以后发生的事情很重要)已经被读取,需要它的代码将无法使用。
解决此问题的一种方法是在数据流中的 XML 之前加上字节数,以便您的循环知道在停止之前要读取多少字节。另一种方法可能是将 XML 转换为二进制,然后转换为 base64(可能首先压缩二进制),然后使用您知道的某些字符分隔 base64 数据对 base64 数据无效(例如 space、换行符、制表符等)。
无论您如何处理它,您都会通过 XML 本身的最终关闭标记以外的某种机制知道 XML 的结尾,因此仍然可以使用 StringBuilder
并且不必在字符串中搜索该结束标记。
我会提供有关后者的更多详细信息,但您没有在问题中提供足够的信息来这样做。如果您需要这方面的具体帮助,请 post 提出一个新问题并确保提供适当的详细信息。有关如何更好地提出问题的建议,请参阅 https://whosebug.com/help/mcve and https://whosebug.com/help/how-to-ask。