包装记录长度为2个字节

时间:2011-03-31 12:42:34

标签: c# .net bit-manipulation bit-shift

我想创建一个包含许多字段的ASCII字符串。例如,

string s = f1 + "|" + f2 + "|" + f3;

f1,f2,f3是字段,“|”(管道)是分隔符。我想避免使用这个分隔符,并将字段数保持在开头,如:

string s = f1.Length + f2.Length + f3.Length + f1 + f2 + f3;

所有长度将打包为2个字符,在这种情况下,最大长度= 00-99。我想知道是否可以通过从短路中提取字节来将每个字段的长度打包为2个字节。这将允许我使用仅2个字节的范围0-65536。 E.g。

short length = 20005;
byte b1 = (byte)length;
byte b2 = (byte)(length >> 8);
// Save bytes b1 and b2

// Read bytes b1 and b2
short length = 0;
length = b2;
length = (short)(length << 8);
length = (short)(length | b1);
// Now length is 20005

您如何看待上述代码,这是保持记录长度的好方法吗?

4 个答案:

答案 0 :(得分:1)

我无法看到你想要实现的目标。 short又名Int16是2个字节 - 是的,所以你可以愉快地使用它。但是创建一个字符串没有意义。

short sh = 56100; // 2 bytes

我相信你的意思是,能够将short输出到流。为此,有方法:

  • BinaryWriter.Write(sh)将2个字节直接写入流
  • BitConverter.GetBytes(sh),它为您提供short
  • 的字节

回读你可以使用相同的类。

答案 1 :(得分:0)

如果你想要 ascii ,即“00”作为字符,那么只需:

byte[] bytes = Encoding.Ascii.GetBytes(length.ToString("00"));

或者你可以根据需要进行优化。

但IMO,如果你要存储0-99,那么1个字节就足够了:

byte b = (byte)length;

如果你想要的范围是0-65535,那么只需:

bytes[0] = (byte)length;
bytes[1] = (byte)(length >> 8);

或交换索引0和1表示字节顺序。

但是如果你使用的是全范围(单字节或双字节),那么不是 ascii也不是字符串。任何试图将其作为字符串读取的东西都可能会失败。

答案 2 :(得分:0)

这是否是一个好主意取决于它的具体细节,但它不是可能是好的。

如果您这样做,那么您将不再创建“ASCII字符串”。那些是你的话,但也许你并不关心它是否是ASCII。

有时您的“字符串”中会得到值为0的字节。如果您使用C语言处理字符串,则可能会造成麻烦。你还会得到各种其他角色 - 换行符,标签符号,逗号等等 - 这可能会混淆那些试图处理你数据的软件。

与(例如)|字符分离的原始计划将更紧凑,更易于人类和软件阅读。唯一明显的缺点是(1)你不能允许带有|的字段值(或者你需要某种类型的转义)和(2)解析速度稍慢。

答案 3 :(得分:0)

如果你想变得聪明,你可以将你的2个字节打包成1,其中字节1的值是&lt; = 127,或者如果值是&gt; = 128,则使用2个字节代替。这种技术使您每个字节丢失1位,但如果您通常具有较小的值,但偶尔会有较大的值,则它会动态增长以适应该值。

您需要做的就是将第8位标记为表示需要读取第2个字节的值。 如果未设置活动字节的第8位,则表示您已完成值。

EG 如果您的值为4,则使用此

|8|7|6|5|4|3|2|1|
|0|0|0|0|0|1|0|0|

如果您的值为128,那么您可以读取第一个字节检查第8位是否为高电平,并读取第1个字节的剩余7位,然后对第2个字节执行相同操作,向左移动7位7位。

|BYTE 0         |BYTE 1         |
|8|7|6|5|4|3|2|1|8|7|6|5|4|3|2|1|
|1|0|0|0|0|0|0|0|0|0|0|0|0|0|0|1|