Remove trailing zeros from byte[]?

2020-02-06 10:37发布

问题:

I'm working with TCP protocol and read from socket and write the data to a byte[] array.
Here is a example of my data:

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

I created a byte[] array with size of 1024. Now I use this method to remove null indexes from it:

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());
}

But it removes also 0x00 indexes that it maybe useful data...
How can I remove the 0s that are not wrapped with non-zero data (trailing 0s)?

回答1:

You should fix the code that's reading from the TCP socket so that you don't read something that you intend to throw away afterwards. It seems like a waste to me.

But to answer your question you could start counting in reverse order until you encounter a non-zero byte. Once you have determined the index of this non-zero byte, simply copy from the source array to the target array:

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;
}


回答2:

This is quite short and fast function to trim trailing zeroes from array.

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

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

    return array;
}


回答3:

As you can't shrink the size of an array by definition you would have to use a dynamic data structure instead.

Use a List for example

List<byte> byteList;

Iterate over your byte array and add each value != 0 to the byteList. When you have reached the end of data in your byteArray break the iteration and discard the array and use the byteList from now on.

for (int i = 0; i <= byteArray.Length; i++) {

    if (byteArray[i] != 0) {

        byteList.Add(byteArray[i]);
    } else {

         break;
    }

}

If you though want to use an array you can create one directly from your list

byte[] newByteArray = byteList.ToArray();


回答4:

So you want to trim the 0x00s at the end and copy it into a new array? That would be:

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);

Although of course probably there can be somehow valid 0x00s at the end too.



回答5:

Actually very close example was given on MSDN site. Really C# 4.5 style - with Predicate<T>. You can try it if you want (although correct answer was already submitted)

MSDN: Predicate Delegate

P.S. I'm still waiting for Linq style answer with Select() and .ToList<byte[]>() at end



回答6:

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


回答7:

Have a nice one line solution pure 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();
    }


标签: c# arrays byte