【问题标题】:C# - Converting a Sequence of Numbers into BytesC# - 将数字序列转换为字节
【发布时间】:2009-07-08 18:08:05
【问题描述】:

我正在尝试按顺序发送对应于数字 1-1000 的 UDP 字节数据包。如何将每个数字 (1,2,3,4,...,998,999,1000) 转换为所需的最小字节数,并将它们放在可以作为 UDP 数据包发送的序列中?

我尝试了以下但没有成功。任何帮助将不胜感激!

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

谢谢。

【问题讨论】:

  • 闻起来像家庭作业。如果有,请相应标记。
  • 尝试 7 位编码的 int。在下面查看我的答案。

标签: c# bytearray


【解决方案1】:

你需要使用:

BitConverter.GetBytes(INTEGER);

【讨论】:

【解决方案2】:

想想你将如何区分:

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

如果您将一个字节用于最多 255 的数字,而将两个字节用于数字 256-1000,那么您将无法在另一端计算出哪个数字对应于什么。

如果您只需要按照描述对它们进行编码而不用担心它们是如何被解码的,那么这对我来说就像是一个人为的家庭作业或测试,我不愿意为您解决它。

【讨论】:

  • 当然可以,只需使用 7 位编码整数即可。这是 BinaryReader/Writers 中用于编码字符串长度的一个小技巧。
  • 我知道,我希望提问者思考答案,因为这是他作业的重点。
【解决方案3】:

我认为您正在寻找类似于 7 位编码整数的东西:

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

(取自System.IO.BinaryWriter.Write(String))。

System.IO.BinaryReader 类中找到相反的内容,看起来像这样:

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

我确实希望这不是家庭作业,即使闻起来真的很像。

编辑:

好的,所以为您整理一下:

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

对于数字 1-1000,我得到的总大小是 1871 字节。 顺便说一句,你能简单地说明这是否是家庭作业吗?显然,无论哪种方式,我们仍然会提供帮助。但我们更希望您能更加努力地尝试,这样您才能真正自学。

编辑#2:

如果你只想打包它们而忽略解码它们的能力,你可以这样做:

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

这将忽略任何为零的字节(从 MSB 到 LSB)。所以对于 0-255 它将使用一个字节。 正如其他地方所述,这将不允许您将数据解码回来,因为流现在是模棱两可的。附带说明一下,这种方法将其压缩到 1743 字节(而不是使用 7 位编码的 1871 字节)。

【讨论】:

  • Erich,我如何将你的函数用于 1-1000 的所有数字?
【解决方案4】:

一个字节只能保存 256 个不同的值,因此您不能将 255 以上的数字存储在一个字节中。最简单的方法是使用 short,即 16 位。如果您确实需要节省空间,可以使用 10 位数字并将其打包成一个字节数组(10 位 = 2^10 = 1024 个可能的值)。

【讨论】:

  • 我必须使用字节。要发送 UDP 数据包,需要发送一个 byte[] 作为消息。你能告诉我如何将每个数字表示为字节吗?我知道超过 255 的数字需要一些逻辑。提前致谢!
  • 如果您确定您永远不需要发送任何高于 1024 的内容,您可以使用每个值 10 位,相当于 1250 字节,大约 31 %只是将每个 int 作为 4 个字节发送的天真的方法。你想要一个这样的例子吗?
  • 德里斯,请。但是,我需要每个值的最小位数,并且 10 位为每个值使用 2 个字节。
【解决方案5】:

天真地(也未经测试):

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

会给你一个字节流,每组 4 个字节是一个数字 [1, 1000]。


您可能想做一些工作,以便 i

我会说,不要。只需使用内置类压缩流,或使用一致同意的频率集启动Huffman encoding 实现。

【讨论】:

  • 我认为这是在正确的轨道上,但每个数字都需要以最小字节数表示。 (即:数字 1-255 只需要 1 个字节)。有什么想法吗?
  • 如果您实际上以您正在寻找的方式减少到最小编码,则必须包括哨兵。这并不一定会导致总大小的减少。稍后我会更新一个更好但不同的方法。
  • Kevin 的解决方案创建了 4000 字节的总流,而我真的需要一个更小的流。像 255 + 2x(1000-255) = 1745 字节。有什么想法吗?
  • 即使我不关心从流中读取值,我将如何添加“i
  • BitConvert 具有适用于所有内置类型的 GetBytes 方法。在调用 GetBytes 之前,只需将 i 转换为 (byte)、(UInt16) 等。
猜你喜欢
  • 1970-01-01
  • 2013-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-11
  • 2019-12-15
  • 1970-01-01
相关资源
最近更新 更多