c# – 左移整个字节数组

在C#中,是否有一种方法可以向右/向左移动整个字节数组(并且随后在最后一位向特定端添加一个字节不会丢失)?

我知道这听起来像一个奇怪的请求,但我仍然想知道它是否可能和/或如何开始这样做。

是的你可以。 请参阅我写的以下方法:

 ///  /// Rotates the bits in an array of bytes to the left. ///  /// The byte array to rotate. public static void RotateLeft(byte[] bytes) { bool carryFlag = ShiftLeft(bytes); if (carryFlag == true) { bytes[bytes.Length - 1] = (byte)(bytes[bytes.Length - 1] | 0x01); } } ///  /// Rotates the bits in an array of bytes to the right. ///  /// The byte array to rotate. public static void RotateRight(byte[] bytes) { bool carryFlag = ShiftRight(bytes); if (carryFlag == true) { bytes[0] = (byte)(bytes[0] | 0x80); } } ///  /// Shifts the bits in an array of bytes to the left. ///  /// The byte array to shift. public static bool ShiftLeft(byte[] bytes) { bool leftMostCarryFlag = false; // Iterate through the elements of the array from left to right. for (int index = 0; index < bytes.Length; index++) { // If the leftmost bit of the current byte is 1 then we have a carry. bool carryFlag = (bytes[index] & 0x80) > 0; if (index > 0) { if (carryFlag == true) { // Apply the carry to the rightmost bit of the current bytes neighbor to the left. bytes[index - 1] = (byte)(bytes[index - 1] | 0x01); } } else { leftMostCarryFlag = carryFlag; } bytes[index] = (byte)(bytes[index] << 1); } return leftMostCarryFlag; } ///  /// Shifts the bits in an array of bytes to the right. ///  /// The byte array to shift. public static bool ShiftRight(byte[] bytes) { bool rightMostCarryFlag = false; int rightEnd = bytes.Length - 1; // Iterate through the elements of the array right to left. for (int index = rightEnd; index >= 0; index--) { // If the rightmost bit of the current byte is 1 then we have a carry. bool carryFlag = (bytes[index] & 0x01) > 0; if (index < rightEnd) { if (carryFlag == true) { // Apply the carry to the leftmost bit of the current bytes neighbor to the right. bytes[index + 1] = (byte)(bytes[index + 1] | 0x80); } } else { rightMostCarryFlag = carryFlag; } bytes[index] = (byte)(bytes[index] >> 1); } return rightMostCarryFlag; } 

只是为了笑容。 在字节数组中移位和旋转字节。 (不是位移)

左移,零填充:

mybytes.Skip(1).Concat(new byte[] { 0 }).ToArray();

右移,零填充:

(new byte[] {0}).Concat(mybytes.Take(mybytes.Length - 1)).ToArray();

向左旋转:

mybytes.Skip(1).Concat(mybytes.Take(1)).ToArray();

右旋:

mybytes.Skip(mbytes.Length - 1).Concat(mbytes.Take(mbytes.Length - 1)).ToArray();

您似乎正在对存储在字节数组中的大量位执行位操作。 考虑使用BitArray类和BitVector32结构。 根据您对位的操作,您可以创建这样的类。 请注意,移位工作在O(1)而不是O(n)。

 public class BitRing : IEnumerable { private readonly BitArray m_InnerBitArray; private int m_StarIndex; public BitRing(byte[] bytes) { m_InnerBitArray = new BitArray(bytes); m_StarIndex = 0; } public void ShiftLeft() { m_StarIndex++; } public void ShiftRight() { m_StarIndex--; } public bool this[int i] { get { int index = GetIndex(i); return m_InnerBitArray[index]; } set { int index = GetIndex(i); m_InnerBitArray[index] = value; } } private int GetIndex(int i) { return i - m_StarIndex%m_InnerBitArray.Count; } public IEnumerator GetEnumerator() { for (int i = m_StarIndex; i < m_InnerBitArray.Count; i++) { yield return m_InnerBitArray[i]; } for (int i = 0; i < m_StarIndex; i++) { yield return m_InnerBitArray[i]; } } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } } 

Linq方式:

 static class Shifter { public static byte[] ShiftLeft(this byte[] array, int n) { var a = array.Select(x => (byte)(x >> 8 - n % 8)).Concat(new byte[(7 + n) / 8]).Select((x, i) => new Tuple(i - (n % 8 == 0 ? 0 : 1), x)); var b = array.Select(x => (byte)(x << n % 8)).Concat(new byte[n / 8]).Select((x, i) => new Tuple(i, x)); return (from x in a join y in b on x.Item1 equals y.Item1 into yy from y in yy.DefaultIfEmpty() select (byte)(x.Item2 | (y == null ? 0 : y.Item2))).ToArray(); } public static byte[] ShiftRight(this byte[] array, int n) { return (new byte[n/8]).Concat(ShiftLeft(array, (8 - (n%8))%8)).ToArray(); } } 

我不认为有内置的方式。 我实现了你在下面描述的左移操作(假设小端)。 它不像你使用x86程序集那样优雅( 带有进位指令的转换 ),但非常接近你可以用C做的事情。

或者,您几乎可以使用BigInteger结构(.NET 4及更高版本),该结构具有采用字节数组和ToByteArray方法的构造函数。 但它的左移操作符号 – 扩展高字节,其右移操作截断。 因此,您需要对两者进行补偿以获得您描述的确切行为。

  // Left-shifts a byte array in place. Assumes little-endian. Throws on overflow. static public void ShiftByteArrayLeft(byte[] array) { if (array == null) throw new ArgumentNullException("array"); if (array[array.Length - 1] >= 0x80) throw new OverflowException(); // move left-to-right, left-shifting each byte for (int i = array.Length - 1; i >= 1; --i) { // left-shift current byte array[i] <<= 1; // carry the bit from the next/right byte if needed if (array[i - 1] >= 0x80) ++array[i]; } // finally shift the left-shift the right-most byte array[0] <<= 1; } // Left-shifts a byte array in place. Assumes little-endian. Grows array as needed. static public void ShiftByteArrayLeftAutoGrow(ref byte[] array) { if (array == null) throw new ArgumentNullException("array"); if (array[array.Length - 1] >= 0x80) { // allocate a bigger array and do the left-shift on it byte[] oldArray = array; array = new byte[oldArray.Length + 1]; Array.Copy(oldArray, 0, array, 0, oldArray.Length); } ShiftByteArrayLeft(array); } 

我已经考虑了一些,并意识到这可能更适合这个问题:

 public static void Main() { byte[] bytes = new byte[] { 0xFF, 0x01, 0x80, 0x81 }; Stack bitStack = CreateBitStack(bytes); ShiftLeftExpand(bitStack, 1); byte[] newBytes = CreateByteArray(bitStack); } public static void ShiftLeftExpand(Stack bitStack, int count) { while (count-- > 0) { bitStack.Push(false); } } public static Stack CreateBitStack(byte[] bytes) { Stack bitStack = new Stack(bytes.Length * 8); for (int bytePosition = 0; bytePosition < bytes.Length; bytePosition++) { for (int bitPosition = 7; bitPosition >= 0; bitPosition--) { int bitMask = 0x01 << bitPosition; bitStack.Push((bytes[bytePosition] & bitMask) > 0); } } return bitStack; } public static byte[] CreateByteArray(Stack bitStack) { int newArrayLength = (int)Math.Ceiling(bitStack.Count / 8.0); byte[] bytes = new byte[newArrayLength]; int bitCounter = 0; while (bitStack.Count > 0) { bool? bitValue = bitStack.Pop(); int bitPosition = bitCounter % 8; int bytePosition = newArrayLength - 1 - bitCounter / 8; if (bitValue == true) { bytes[bytePosition] = (byte)(bytes[bytePosition] | (0x01 << bitPosition)); } bitCounter++; } return bytes; } 

可以应用类似的技术来执行右移。