5

我正在使用 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)?

4

7 回答 7

15

这是从数组中修剪尾随零的非常短而快速的功能。

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

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

    return array;
}
于 2014-12-01T09:25:01.013 回答
12

您应该修复从 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;
}
于 2012-06-29T14:20:15.643 回答
2

有一个很好的单行解决方案纯 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();
    }
于 2019-11-05T18:20:52.310 回答
1

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

以列表为例

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();
于 2012-06-29T14:21:18.607 回答
0

所以你想修剪最后的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);

虽然当然最后也可能有某种有效0x00的 s 。

于 2012-06-29T14:21:25.483 回答
0

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

MSDN:谓词委托

PS我仍在等待Linq风格的答案Select().ToList<byte[]>()最后

于 2012-06-29T15:01:59.827 回答
0
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
于 2015-03-22T14:21:27.573 回答