【发布时间】:2018-12-23 08:22:51
【问题描述】:
这个问题是对我上一个问题的跟进: Link
在那个问题中,我询问了如何阅读特定的 VLQ 格式,我不会再次描述,但您可以从我之前的问题中阅读。
harold 的结果基本上是这样的:
static int ReadVLQInt64(this BinaryReader r)
{
sbyte b0 = r.ReadSByte();
// the first byte has 6 bits of the raw value
int shift = 6;
long raw = b0 & 0x3FL;
// first continue flag is the second bit from the top, shift it into the sign
sbyte cont = (sbyte)(b0 << 1);
while (cont < 0)
{
sbyte b = r.ReadSByte();
// these bytes have 7 bits of the raw value
raw |= (b & 0x7F) << shift;
shift += 7;
// continue flag is already in the sign
cont = b;
}
return b0 < 0 ? -raw : raw;
}
(这只是它的 int64 版本)
这很好地读取这样的值,但现在我需要能够写入这样的值。 简而言之,我需要该功能的反面。获取一个 int64 值并将其分解为上一个问题中描述的格式的可变长度字节数组。
任何帮助将不胜感激。
感谢阅读。
编辑:应 cmets 的要求,我需要提供一些我自己的代码来构建。
public static void WriteVLQInt64(this BinaryWriter bw, long value)
{
var bytes = new List<byte>();
var i = 6;
var j = 0;
var shift = 0;
while (true)
{
var andvalue = Convert.ToInt64(Math.Pow(2, i) - Math.Pow(2, j));
j = i;
var b = Convert.ToByte((value & andvalue) >> shift);
if (b <= 0) break;
bytes.Add(b);
shift = i;
i += 7;
}
for (int k = 0; k < bytes.Count; k++)
{
if (bytes[k] == bytes.First())
{
if (value < 0)
{
bytes[k] |= 128;
}
if (bytes[k] != bytes.Last())
{
bytes[k] |= 64;
}
continue;
}
if (bytes[k] != bytes.Last())
{
bytes[k] |= 128;
}
}
bw.Write(bytes.ToArray());
/* - Just for debug
foreach (var item in bytes)
{
Console.Write(Convert.ToString(item, 2).PadLeft(8, '0'));
}
Console.WriteLine();
*/
}
我之前没有发布这个只是因为它是一个非常混乱的解决方案,并且有太多的事情要做。 所以我将重新提出我的问题......是否有人可以帮助我压缩该功能并从中删除很多不必要的东西?例如 Math.Pow 中的大量 if 语句和 Convert.To 的大量使用...
再次感谢您的阅读。
【问题讨论】:
-
与往常一样,SO 不是“为我编写代码”...您编写一些代码,我们帮助您。你写0代码,我们不用帮你。
-
好的,我用我自己的一些乱码更新了帖子。
-
提醒一下,64 位版本需要
b & 0x7FL,但不需要b0 & 0x3FL(对于第一个字节,位永远不会移出int的范围,它们甚至不是转移)。
标签: c# binary bit-manipulation .net-4.7.1