【问题标题】:Remove trailing zeros from byte[]?从 byte[] 中删除尾随零?
【发布时间】:2012-07-01 01:47:03
【问题描述】:

我正在使用 TCP 协议并从套接字读取并将数据写入 byte[] 数组。
这是我的数据示例:

94 39 E5 D9 32 83
D8 5D 4C B1 CB 99 
08 00 45 00 00 98 
41 9F 40 00 6C 06 
9C 46 26 50 48 7D 
C0 A8 01 05 03 28

我创建了一个大小为 1024 的 byte[] 数组。现在我使用此方法从中删除空索引:

public void Decode(byte[] packet)
{
    byte[] temp;
    int c = 0;
    foreach(byte x in packet)
        if (x != 0)
            c++;
    temp = new byte[c];
    for (int i = 0; i < c; i++)
        temp[i] = packet[i];
    MessageBox.Show(temp.Length.ToString());
}

但它也会删除可能有用数据的 0x00 索引...
如何删除未使用非零数据(尾随 0)包裹的 0?

【问题讨论】:

  • 如何判断零是否“有用”?
  • 空索引是什么意思?
  • @harold 因为订单对我来说非常重要...
  • 数组中的索引不能为空。既不是值,因为byte 是值类型。是否要从数组中删除 0x00 值?
  • 当你的 byte[] 被填充时,你应该在某处得到一个值,告诉你读取了多少字节(这目前可能是来自被忽略的 Read 方法的返回值)。您应该使用它来调整数组的大小,而不是仅仅从末尾修剪 0。

标签: c# arrays byte


【解决方案1】:

这是一个非常短且快速的函数,用于从数组中修剪尾随零。

public static byte[] TrimEnd(byte[] array)
{
    int lastIndex = Array.FindLastIndex(array, b => b != 0);

    Array.Resize(ref array, lastIndex + 1);

    return array;
}

【讨论】:

    【解决方案2】:

    您应该修复从 TCP 套接字读取的代码,这样您就不会读取您打算在之后丢弃的东西。这对我来说似乎是一种浪费。

    但是要回答您的问题,您可以开始以相反的顺序计数,直到遇到非零字节。一旦确定了这个非零字节的索引,只需从源数组复制到目标数组:

    public byte[] Decode(byte[] packet)
    {
        var i = packet.Length - 1;
        while(packet[i] == 0)
        {
            --i;
        }
        var temp = new byte[i + 1];
        Array.Copy(packet, temp, i + 1);
        MessageBox.Show(temp.Length.ToString());
        return temp;
    }
    

    【讨论】:

      【解决方案3】:

      有一个不错的纯 LINQ 单行解决方案:

          public static byte[] TrimTailingZeros(this byte[] arr)
          {
              if (arr == null || arr.Length == 0)
                  return arr;
              return arr.Reverse().SkipWhile(x => x == 0).Reverse().ToArray();
          }
      

      【讨论】:

        【解决方案4】:

        由于您无法根据定义缩小数组的大小,因此您必须改用动态数据结构。

        以列表为例

        List<byte> byteList;
        

        遍历您的字节数组并将每个值 != 0 添加到 byteList。当您到达 byteArray 中的数据末尾时,中断迭代并丢弃数组并从现在开始使用 byteList。

        for (int i = 0; i <= byteArray.Length; i++) {
        
            if (byteArray[i] != 0) {
        
                byteList.Add(byteArray[i]);
            } else {
        
                 break;
            }
        
        }
        

        如果你想使用一个数组,你可以直接从你的列表中创建一个

        byte[] newByteArray = byteList.ToArray();
        

        【讨论】:

        • 这将在第一个 0 字节处停止,之后可能会修剪非零字节。 OP 只想删除数组末尾的连续零字节。
        • 当然你是对的 :) 但我不会删除帖子,也许这让他知道如何使用 List ..
        【解决方案5】:

        所以你想修剪最后的0x00s 并将其复制到一个新数组中?那将是:

        int endIndex = packet.Length - 1;
        while (endIndex >= 0 && packet[endIndex] == 0)
            endIndex--;
        
        byte[] result = new byte[endIndex + 1];
        Array.Copy(packet, 0, result, 0, endIndex + 1);
        

        当然,最后也可能有某种有效的0x00s。

        【讨论】:

          【解决方案6】:

          实际上非常接近的例子是在 MSDN 网站上给出的。真正的 C# 4.5 风格 - Predicate&lt;T&gt;。如果你愿意,你可以试试(虽然正确答案已经提交)

          MSDN: Predicate Delegate

          附:我仍在等待 Linq 风格的答案,最后是 Select().ToList&lt;byte[]&gt;()

          【讨论】:

            【解决方案7】:
            Byte[] b = new Byte[1024]; // Array of 1024 bytes
            
            List<byte> byteList; // List<T> of bytes
            
            // TODO: Receive bytes from TcpSocket into b
            
            foreach(var val in b) // Step through each byte in b
            {
            
                if(val != '0') // Your condition
                {
                }
                else
                {
                    bytelist.Add(val); //Add the byte to the List
                }
            }
            bytelist.ToArray(); // Convert the List to an array of bytes
            

            【讨论】:

              猜你喜欢
              • 2012-07-02
              • 2011-05-30
              • 2015-06-16
              • 2012-01-26
              • 1970-01-01
              • 1970-01-01
              • 2012-06-28
              • 1970-01-01
              • 2020-01-25
              相关资源
              最近更新 更多