0

I am trying to send a UDP packet of bytes corresponding to the numbers 1-1000 in sequence. How do I convert each number (1,2,3,4,...,998,999,1000) into the minimum number of bytes required and put them in a sequence that I can send as a UDP packet?

I've tried the following with no success. Any help would be greatly appreciated!

 List<byte> byteList = new List<byte>();

        for (int i = 1; i <= 255; i++)
        {
            byte[] nByte = BitConverter.GetBytes((byte)i);
            foreach (byte b in nByte)
            {
                byteList.Add(b);
            }
        }

        for (int g = 256; g <= 1000; g++)
        {
            UInt16 st = Convert.ToUInt16(g);
            byte[] xByte = BitConverter.GetBytes(st);
            foreach (byte c in xByte)
            {
                byteList.Add(c);
            }
        }


        byte[] sendMsg = byteList.ToArray();

Thank you.

2
  • 6
    smells like homework. if so, please tag correspondingly. Commented Jul 8, 2009 at 18:49
  • try the 7-bit encoded int. check out my answer below. Commented Jul 8, 2009 at 19:17

5 Answers 5

6

You need to use :

BitConverter.GetBytes(INTEGER);
Sign up to request clarification or add additional context in comments.

3 Comments

I think you are missing the point that he needs to pack the numbers into a minimum number of bytes total.
driis, see Matt's answer below : stackoverflow.com/questions/1099691/…
Moayad, take a look at my answer :)
3

Think about how you are going to be able to tell the difference between:

260, 1  -> 0x1, 0x4, 0x1
1, 4, 1 -> 0x1, 0x4, 0x1

If you use one byte for numbers up to 255 and two bytes for the numbers 256-1000, you won't be able to work out at the other end which number corresponds to what.

If you just need to encode them as described without worrying about how they are decoded, it smacks to me of a contrived homework assignment or test, and I'm uninclined to solve it for you.

2 Comments

Sure you can, just use 7-bit encoded integers. It's a little trick used in the BinaryReader/Writers for encoding the length of a string.
I know that, I want the questioner to think about the answer as that is the point of his homework.
2

I think you are looking for something along the lines of a 7-bit encoded integer:

protected void Write7BitEncodedInt(int value)
{
    uint num = (uint) value;
    while (num >= 0x80)
    {
        this.Write((byte) (num | 0x80));
        num = num >> 7;
    }
    this.Write((byte) num);
}

(taken from System.IO.BinaryWriter.Write(String)).

The reverse is found in the System.IO.BinaryReader class and looks something like this:

protected internal int Read7BitEncodedInt()
{
    byte num3;
    int num = 0;
    int num2 = 0;
    do
    {
        if (num2 == 0x23)
        {
            throw new FormatException(Environment.GetResourceString("Format_Bad7BitInt32"));
        }
        num3 = this.ReadByte();
        num |= (num3 & 0x7f) << num2;
        num2 += 7;
    }
    while ((num3 & 0x80) != 0);
    return num;
}

I do hope this is not homework, even though is really smells like it.

EDIT:

Ok, so to put it all together for you:

using System;
using System.IO;

namespace EncodedNumbers
{
    class Program
    {
        protected static void Write7BitEncodedInt(BinaryWriter bin, int value)
        {
            uint num = (uint)value;
            while (num >= 0x80)
            {
                bin.Write((byte)(num | 0x80));
                num = num >> 7;
            }
            bin.Write((byte)num);
        }


        static void Main(string[] args)
        {
            MemoryStream ms = new MemoryStream();
            BinaryWriter bin = new BinaryWriter(ms);

            for(int i = 1; i < 1000; i++)
            {
                Write7BitEncodedInt(bin, i);
            }

            byte[] data = ms.ToArray();
            int size = data.Length;
            Console.WriteLine("Total # of Bytes = " + size);

            Console.ReadLine();
        }
    }
}

The total size I get is 1871 bytes for numbers 1-1000. Btw, could you simply state whether or not this is homework? Obviously, we will still help either way. But we would much rather you try a little harder so you can actually learn for yourself.

EDIT #2:

If you want to just pack them in ignoring the ability to decode them back, you can do something like this:

    protected static void WriteMinimumInt(BinaryWriter bin, int value)
    {
        byte[] bytes = BitConverter.GetBytes(value);
        int skip = bytes.Length-1;
        while (bytes[skip] == 0)
        {
            skip--;
        }
        for (int i = 0; i <= skip; i++)
        {
            bin.Write(bytes[i]);
        }
    }

This ignores any bytes that are zero (from MSB to LSB). So for 0-255 it will use one byte. As states elsewhere, this will not allow you to decode the data back since the stream is now ambiguous. As a side note, this approach crams it down to 1743 bytes (as opposed to 1871 using 7-bit encoding).

1 Comment

Erich, how do I use your functions for all the numbers 1-1000?
1

A byte can only hold 256 distinct values, so you cannot store the numbers above 255 in one byte. The easiest way would be to use short, which is 16 bits. If you realy need to conserve space, you can use 10 bit numbers and pack that into a byte array ( 10 bits = 2^10 = 1024 possible values).

3 Comments

I have to use bytes. To send a UDP packet requires sending a byte[] as the message. Can you please tell me how to express each number as bytes? I understand there will need to be some logic for numbers over 255. Thanks in advance!
If you are sure you never need to send anything above 1024, you can make do with 10 bits per value, which works out to 1250 bytes, which is about 31 % of the naive method of just sending each int as 4 bytes. Would you like an example of that ?
Driis, yes please. However, I need the minimum number of bits per value, and 10 bits is using 2 bytes for each value.
0

Naively (also, untested):

List<byte> bytes = new List<byte>();

for (int i = 1; i <= 1000; i++)
{
    byte[] nByte = BitConverter.GetBytes(i);
    foreach(byte b in nByte) bytes.Add(b);
}

byte[] byteStream = bytes.ToArray();

Will give you a stream of bytes were each group of 4 bytes is a number [1, 1000].


You might be tempted to do some work so that i < 256 take a single byte, i < 65535 take two bytes, etc. However, if you do this you can't read the values out of the stream. Instead, you'd add length encoding or sentinels bits or something of the like.

I'd say, don't. Just compress the stream, either using a built-in class, or gin up a Huffman encoding implementation using an agree'd upon set of frequencies.

7 Comments

I think this is on the right track, but each number needs to be expressed in the minimum number of bytes. (ie: numbers 1-255 only require 1 byte). Any ideas?
You have to include sentinels if you actually reduce to minimum encoding in the fashion you're looking for. This does not necessarily result in a reduction in the total size. I'll update with a better, but different, approach in a second.
Kevin's solution creates a total stream of 4000 bytes, when I really need a smaller stream. Something like 255 + 2x(1000-255) = 1745 bytes. Any thoughts?
Even if I didn't care about reading the values out of the stream, how would I add the logic such that "i < 256 take a single byte, i < 65535 take two bytes"?
BitConvert has GetBytes methods for all built-in types. Simply cast i to (byte), (UInt16), etc. before calling GetBytes.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.