Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/317.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从字节数组读取行(不将字节数组转换为字符串)_C#_.net_Bytearray_Networkstream - Fatal编程技术网

C# 从字节数组读取行(不将字节数组转换为字符串)

C# 从字节数组读取行(不将字节数组转换为字符串),c#,.net,bytearray,networkstream,C#,.net,Bytearray,Networkstream,我有一个从网络流中读取的字节数组。前两个字节告诉后面的数据包的长度,然后数据包被读入该长度的字节数组。我需要从NetworkStream/字节数组中读取的数据有几个字符串,即以新行字符结尾的可变长度数据,以及一些固定宽度的字段,如字节和长度。比如说: // I would have delimited these for clarity but I didn't want // to imply that the stream was delimited because it's not. St

我有一个从网络流中读取的字节数组。前两个字节告诉后面的数据包的长度,然后数据包被读入该长度的字节数组。我需要从NetworkStream/字节数组中读取的数据有几个字符串,即以新行字符结尾的可变长度数据,以及一些固定宽度的字段,如字节和长度。比如说:

// I would have delimited these for clarity but I didn't want
// to imply that the stream was delimited because it's not.
StringbyteStringStringbytebytebytelonglongbytelonglong
我知道(并且有一些发言权)遇到的数据包的格式,我需要做的是为每个字符串值读取一个“行”,但为字节和长度读取固定数量的字节。到目前为止,我建议的解决方案是使用
while
循环将字节读入临时字节数组,直到出现换行符为止。然后,将字节转换为字符串。这对我来说似乎很难理解,但我看不出另一种明显的方式。我意识到我可以使用
StreamReader.ReadLine()
,但这将涉及另一个流,我已经有了
NetworkStream
。但如果这是更好的解决方案,我会试试看

我考虑过的另一个选择是让我的后端团队为那些字符串值的长度写一两个字节,这样我就可以读取长度,然后根据指定的长度读取字符串

<> P>所以,正如你所看到的,我有一些选择来讨论这个问题,我想输入你认为最好的方法。下面是我现在所拥有的代码,用于将整个数据包作为字符串读取。下一步是分解数据包的各个字段,并根据数据包中的数据进行实际的编程工作,创建对象、更新UI等

string line = null;  
while (stream.DataAvailable)
{  
    //Get the packet length;  
    UInt16 packetLength = 0;  
    header = new byte[2];  
    stream.Read(header, 0, 2);  
    // Need to reverse the header array for BitConverter class if architecture is little endian.  
    if (BitConverter.IsLittleEndian)
        Array.Reverse(header);  
    packetLength = BitConverter.ToUInt16(header,0);

    buffer = new byte[packetLength];
    stream.Read(buffer, 0, BitConverter.ToUInt16(header, 0));
    line = System.Text.ASCIIEncoding.ASCII.GetString(buffer);
    Console.WriteLine(line);
}
我个人会的

  • 将Int16放在程序的开头 字符串,所以你知道有多长 他们会的,而且
  • 使用IO.BinaryReader类 做阅读,它会“阅读”,ints, 将字符串、字符等放入变量中,例如BinReader.ReadInt16()将读取两个字节,返回它们表示的int16,并在流中移动两个字节
  • 希望这有帮助

    注意:使用ReadString方法时要小心,它假定字符串前面有自定义的7位整数,即它是由BinaryWriter类编写的。 以下是这篇文章的内容

    BinaryWriter类有两个方法 用于编写字符串:重载 Write()方法和WriteString()函数 方法。前者写字符串 根据 对正在使用的类进行编码。这个 WriteString()方法还使用 指定了编码,但它有前缀 字符串的字节流与 字符串的实际长度。这样的 前缀字符串通过via读回 BinaryReader.ReadString()

    关于长度的有趣的事情 将其值设置为尽可能少的字节 是用来装这个尺寸的,是吗 存储为一种称为7位的类型 编码整数。如果长度合适的话 如果是,则使用单个字节的7位 大于此值,则显示高位 设置第一个字节,第二个字节 字节是通过移位值创建的 7位。这是重复的 连续字节,直到有 足够的字节来保存该值。这 该机制用于确保 长度不会变成一个数字 所占面积的很大一部分 由序列化字符串向上扩展。 BinaryWriter和BinaryReader 读取和写入7位数据的方法 编码的整数,但它们是 受保护,因此您只能使用它们 如果您从这些类派生


    我会使用长度前缀字符串。这将使你的生活简单得多,这意味着你可以用换行符来表示字符串。不过,对您的代码有一些评论:

    • 不要使用Stream.DataAvailable。现在没有可用的数据并不意味着您已经读取了流的末尾
    • 除非您绝对确定永远不需要ASCII以外的文本,否则不要使用ASCII编码
    • 不要假设Stream.Read将读取您要求它读取的所有数据。始终检查返回值
    • BinaryReader使这方面的工作变得更加容易(包括长度前缀字符串和循环读取,直到它读取您要求它读取的内容)
    • 对同一数据调用BitConverter.ToUInt16两次。为什么?

    以前从未遇到过BinaryReader。这看起来对我正在研究的所有东西都非常有帮助。谢谢是的,BinaryReader不适用于我们,因为数据是由Java应用程序写入线程的。最后,我通过读取字节数组,然后根据数据包结构对其进行诅咒,从而“粗暴地强迫”了它。