I have the following 5 bytes in the attached image and need to extract the datetime from it. I understand I'll need to bit shift and maybe use bitwise and's, but fail to get the correct information from the bytes.
Maybe this?
int yearBase = 1993;
int year = yearBase + (int) ((bytes[4] & 0xF0) >> 4) | ((bytes[3] & 0xE0) >> 1);
int month = (int) (bytes[4] & 0x0F);
int day = (int) (bytes[3] & 0x1F);
int hour = (int) ((bytes[2] & 0xF8) >> 3);
int min = (int) (((bytes[2] & 0x03) << 3) | ((bytes[1] & 0xE0) >> 5));
int sec = (int) ((bytes[1] & 0x1F) << 1) | ((bytes[0] & 0x80) >> 7);
int hundreths = (int) (bytes[0] & 0x7F);
I recently answer a question about bitshifting and integer packing in C#.
May be helper class written in that case can be usefull to you as starting point
public static class BinaryConverter
{
public static BitArray ToBinary(this int numeral)
{
return new BitArray(new[] { numeral });
}
public static int ToNumeral(this BitArray binary)
{
if (binary == null)
throw new ArgumentNullException("binary");
if (binary.Length > 32)
throw new ArgumentException("must be at most 32 bits long");
var result = new int[1];
binary.CopyTo(result, 0);
return result[0];
}
public static BitArray Take (this BitArray current, int length )
{
if (current.Length < length)
throw new Exception("Invalid length parameter");
List<bool> taken = new List<bool>();
for (int i = 0; i < length; i++)
taken.Add(current.Get(i));
return new BitArray(taken.ToArray());
}
public static BitArray Shift (this BitArray current, int length )
{
if (current.Length < length)
throw new Exception("Invalid length parameter");
List<bool> shifted = new List<bool>();
for (int i = 0; i < current.Length - length; i++)
shifted.Add(current.Get(length + i));
return new BitArray(shifted.ToArray());
}
public static BitArray FitSize (this BitArray current, int size)
{
List<bool> bools = new List<bool>() ;
bools = bools.InitBoolArray(size);
for (int i = 0; i < current.Count; i++)
bools[i] = current.Get(i) ;
return new BitArray(bools.ToArray());
}
public static List<bool> InitBoolArray(this List<bool> current, int size)
{
List<bool> bools = new List<bool> ();
for (int i = 0; i < size; i++)
bools.Add(false);
return bools ;
}
Here the reference to that answer
Dynamic Bit Shifting / Unshifting
At the link above is displayed how pack small number on the same integer, your five bytes is pretty close to that question
Related
This question already has answers here:
How do you convert a byte array to a hexadecimal string, and vice versa?
(53 answers)
Closed 5 years ago.
Can we convert a hex string to a byte array using a built-in function in C# or do I have to make a custom method for this?
Here's a nice fun LINQ example.
public static byte[] StringToByteArray(string hex) {
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
I did some research and found out that byte.Parse is even slower than Convert.ToByte.
The fastest conversion I could come up with uses approximately 15 ticks per byte.
public static byte[] StringToByteArrayFastest(string hex) {
if (hex.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[hex.Length >> 1];
for (int i = 0; i < hex.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
}
return arr;
}
public static int GetHexVal(char hex) {
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
// also works on .NET Micro Framework where (in SDK4.3) byte.Parse(string) only permits integer formats.
The following code changes the hexadecimal string to a byte array by parsing the string byte-by-byte.
public static byte[] ConvertHexStringToByteArray(string hexString)
{
if (hexString.Length % 2 != 0)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString));
}
byte[] data = new byte[hexString.Length / 2];
for (int index = 0; index < data.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
data[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return data;
}
I think this may work.
public static byte[] StrToByteArray(string str)
{
Dictionary<string, byte> hexindex = new Dictionary<string, byte>();
for (int i = 0; i <= 255; i++)
hexindex.Add(i.ToString("X2"), (byte)i);
List<byte> hexres = new List<byte>();
for (int i = 0; i < str.Length; i += 2)
hexres.Add(hexindex[str.Substring(i, 2)]);
return hexres.ToArray();
}
I have some example code for Crc-64 Table generator. I tried to check the unsigned integer's sign and discovered that it generates mixed table Constants both negative & positive integers. Same for the Crc-64 Checksum, it may be negative or positive. Is it possible to implement a modified Crc-64 Table generator that should produce all negative signed Constants and also the Checksum? Or otherwise all positive signed Constants and Checksum. Kindly help me with some information and example implementation.
Here is the example code for the Crc-64 Table generator:
public class Crc64
{
public const UInt64 POLYNOMIAL = 0xD800000000000000;
public UInt64[] CRCTable;
public Crc64()
{
this.CRCTable = new ulong[256];
for (int i = 0; i <= 255; i++)
{
int j;
UInt64 part = (UInt64)i;
for (j = 0; j < 8; j++)
{
if ((part & 1) != 0)
part = (part >> 1) ^ POLYNOMIAL;
else
part >>= 1;
}
CRCTable[i] = part;
}
}
}
UPDATE: Kindly inform, is this implementation correct as per my question:
public static List<UInt64> generateCrcTable(UInt64 POLY)
{
const ulong TOPBIT_MASK = 0x8000000000000000;
const ulong LOWBIT_MASK = 0x0000000000000001;
List<UInt64> list = new List<UInt64>();
for (int i = 0; i <= 255; i++)
{
UInt64 part = (UInt64)(i); // << 56;
for (byte bit = 0; bit < 63; bit++)
{
if ((part & LOWBIT_MASK) != 0) // 0x8000000000000000) != 0) //1) != 0) // 0x8000000000000000) != 0)
{
part >>= 1;
part ^= POLY;
}
else
{
part >>= 1;
//currentValue |= 0x8000000000000000;
}
}
part |= TOPBIT_MASK; // 0x8000000000000000;
list.Add(part);
}
return list;
}
I got code to work. No table. crc2 is always zero. I run CRC twice. Once to create CRC then add CRC to original data. Then run again to validate.
if you only want 63 bits then change the shift from 56 to 55. Then use mask starting with 0x4 instead of 0x8. And then on the return AND with 0x7FFFFFFFFFFFFFFF
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Random rand = new Random();
List<byte> data = Enumerable.Range(0, 1000).Select(x => (byte)rand.Next(0,256)).ToList();
ulong crc = Crc64.ComputeCrc64(data);
List<byte> results = new List<byte>();
for (int i = 7; i >= 0; i--)
{
results.Add((byte)((crc >> (8 * i)) & 0xFF));
}
data.AddRange(results);
ulong crc2 = Crc64.ComputeCrc64(data);
}
}
public class Crc64
{
const ulong POLYNOMIAL = 0xD800000000000000;
public static ulong ComputeCrc64(List<byte> data)
{
ulong crc = 0; /* CRC value is 64bit */
foreach (byte b in data)
{
crc ^= (ulong)b << 56; /* move byte into MSB of 63bit CRC */
for (int i = 0; i < 8; i++)
{
if ((crc & 0x8000000000000000) != 0) /* test for MSB = bit 63 */
{
crc = (ulong)((crc << 1) ^ POLYNOMIAL);
}
else
{
crc <<= 1;
}
}
}
return crc;
}
}
}
I'm currently trying to shift a BitArray while keeping its length. Since there's no built-in method I'm struggling to build one but can't make it work, unfortunatly.
My initial BitArray code sets a length of 421 for the BitArray.
var b = new BitArray(length: 421);
Than, I'm assigning some values for testing. For instance:
b.Set(0, true);
b.Set(1, true);
However, I can't figure out how to shift the bit array.
Attempts:
- I thought that I could convert it into long and than make the bit manipulation. However, long does not match my exact BitArray length, which results in errors later on when I apply bitwise operations on two BitArrays (my full requirements is (array1 |= array2 >> 20).
- I tried to convert the BitArray into byte[], do the manipulation and return it (see Bit shifting N bits):
public static byte[] ToBytesArray(this BitArray array, int startIndex, int count)
{
// Get the size of bytes needed to store all bytes
int bytesize = count / ByteLength;
// Any bit left over another byte is necessary
if (count % ByteLength > 0)
{
bytesize++;
}
// For the result
byte[] bytes = new byte[bytesize];
// Must init to good value, all zero bit byte has value zero
// Lowest significant bit has a place value of 1, each position to
// to the left doubles the value
byte value = 0;
byte significance = 1;
int bytepos = 0;
int bitpos = startIndex;
while (bitpos - startIndex < count)
{
// If the bit is set add its value to the byte
if (array[bitpos])
value += significance;
bitpos++;
if (bitpos % ByteLength == 0)
{
// A full byte has been processed, store it
// increase output buffer index and reset work values
bytes[bytepos] = value;
bytepos++;
value = 0;
significance = 1;
}
else
{
// Another bit processed, next has doubled value
significance *= 2;
}
}
return bytes;
}
public static BitArray ShiftLeft(this BitArray array, int bitcount)
{
byte[] value = array.ToBytesArray();
byte[] temp = new byte[value.Length];
if (bitcount >= 8)
{
Array.Copy(value, bitcount / 8, temp, 0, temp.Length - (bitcount / 8));
}
else
{
Array.Copy(value, temp, temp.Length);
}
if (bitcount % 8 != 0)
{
for (int i = 0; i < temp.Length; i++)
{
temp[i] <<= bitcount % 8;
if (i < temp.Length - 1)
{
temp[i] |= (byte)(temp[i + 1] >> 8 - bitcount % 8);
}
}
}
return new BitArray(temp);
}
However, byte's length is 8, which can't fit well with my length too. The result is 416 or 424 (another byte) instead of 421.
Finally, I tried the "primitive" way:
for (int i = 0; i < bitcount; i++)
{
var lastValue = array[0];
for (var j = 0; j < array.Length - 1; j++)
{
array[j] = array[j + 1];
}
array[array.Length - 1] = lastValue;
}
I also check up SO (e.g. BitArray - Shift bits) but nothing worked for me.
Any help will be very appreciated!
Still not 100% sure what's the issue. Here's a naive implementation:
void Main()
{
// Creates and initializes a BitArrays of size 7 (you have 421).
bool[] myBools = new bool[7] { true,false,false,true,true,false,true };
BitArray myBA1 = new BitArray(myBools );
PrintBitArray(myBA1); // 1001101
PrintBitArray(ShiftRight(myBA1)); // 0100110
PrintBitArray(ShiftLeft (myBA1)); // 0011010
}
BitArray ShiftRight(BitArray aSource) {
bool[] new_arr = new bool[( aSource.Count)];
for (int i = 0; i < aSource.Count -1; i++)
new_arr[i+1] = aSource[i];
return new BitArray(new_arr);
}
BitArray ShiftLeft(BitArray aSource) {
bool[] new_arr = new bool[( aSource.Count)];
for (int i = 0; i < aSource.Count -1; i++)
new_arr[i] = aSource[i+1];
return new BitArray(new_arr);
}
string PrintBitArray(BitArray aSource) {
StringBuilder sb = new StringBuilder();
foreach (var bit in aSource)
{
sb.Append( (bool)bit ? 1 : 0 );
}
return sb.ToString();
}
Note how bits are copied in the loops, and that the third PrintBitArray is done on the original input, not on the outcome of the second.
public static bool[] Left_shiftBitArray(bool[] Array, int count)
{
Array = BitArray_LRotat(Array, count);
for (int i=Array.GetLength(0)-1; i>=(Array.GetLength(0)-count); i--)
{
Array[i] = false;
}
return Array;
}
public static bool[] BitArray_LRotat(bool[] input, int x)
{
//bool [] temp= new bool[input.Length];
bool[] final = new bool[input.Length];
for (int i = input.Length; i > x; i--)
{
final[i - x - 1] = input[i - 1];
}
for (int i = x; i > 0; i--)
{
final[(input.Length) - i] = input[x - i];
}
return final;
}
byte[] sample = new byte[]{10,20,30};
-the value is 6 bits and started from third bit (from right to left)
new byte[]{10,20,30} looks like "00001010 00010100 00011110" (should be in order like bytes order)
so i need "00001010 00010100 *000111*10"
-my value is 7
the solution based on help(answer 1 by Yaur), just bits direction changed
public static bool GetValue(byte[] data, int position)
{
var bytePos = data.Length - 1 - position / 8;//right -> left
//var bytePos = position / 8;//left -> right
var bitPos = position % 8;
return ((data[bytePos] & (1 << bitPos)) != 0);//right -> left
//return ((data[bytePos] & (1 << (7 - bitPos))) != 0); //left -> right
}
public static long GetValue(byte[] data, int position, int length)
{
if (length > 62)
{
throw new ArgumentException("not going to work properly with 63 bits if the first bit is 1");
}
long retv = 0;
for (int i = position + length - 1; i > position - 1; i--)
//for(int i = position;i<position+length;i++)//left -> right
{
if (GetValue(data, i)) retv |= 1;
retv = retv << 1;
}
retv = retv >> 1;
return retv;
}
This should work for most inputs:
public bool GetValue(byte[] data, int position)
{
var bytePos = position / 8;
var bitPos = position % 8;
return ((data[bytePos] & (1 << bitPos))!=0)
// depending on the order in which you expect the bits you might need this instead
//return ((data[bytePos] & (1 << (7-bitPos)))!=0)
}
public long GetValue(byte[] data, int position, int length)
{
if(length > 62)
{
throw new ArgumentException("not going to work properly with 63 bits if the first bit is 1");
}
long retv=0;
for(int i = position;i<position+length;i++)
{
if(GetValue(data,i)
{
retv |=1;
}
retv = retv << 1;
}
retv = retv >> 1;
}
This question already has answers here:
How do you convert a byte array to a hexadecimal string, and vice versa?
(53 answers)
Closed 5 years ago.
Can we convert a hex string to a byte array using a built-in function in C# or do I have to make a custom method for this?
Here's a nice fun LINQ example.
public static byte[] StringToByteArray(string hex) {
return Enumerable.Range(0, hex.Length)
.Where(x => x % 2 == 0)
.Select(x => Convert.ToByte(hex.Substring(x, 2), 16))
.ToArray();
}
I did some research and found out that byte.Parse is even slower than Convert.ToByte.
The fastest conversion I could come up with uses approximately 15 ticks per byte.
public static byte[] StringToByteArrayFastest(string hex) {
if (hex.Length % 2 == 1)
throw new Exception("The binary key cannot have an odd number of digits");
byte[] arr = new byte[hex.Length >> 1];
for (int i = 0; i < hex.Length >> 1; ++i)
{
arr[i] = (byte)((GetHexVal(hex[i << 1]) << 4) + (GetHexVal(hex[(i << 1) + 1])));
}
return arr;
}
public static int GetHexVal(char hex) {
int val = (int)hex;
//For uppercase A-F letters:
//return val - (val < 58 ? 48 : 55);
//For lowercase a-f letters:
//return val - (val < 58 ? 48 : 87);
//Or the two combined, but a bit slower:
return val - (val < 58 ? 48 : (val < 97 ? 55 : 87));
}
// also works on .NET Micro Framework where (in SDK4.3) byte.Parse(string) only permits integer formats.
The following code changes the hexadecimal string to a byte array by parsing the string byte-by-byte.
public static byte[] ConvertHexStringToByteArray(string hexString)
{
if (hexString.Length % 2 != 0)
{
throw new ArgumentException(String.Format(CultureInfo.InvariantCulture, "The binary key cannot have an odd number of digits: {0}", hexString));
}
byte[] data = new byte[hexString.Length / 2];
for (int index = 0; index < data.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
data[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
}
return data;
}
I think this may work.
public static byte[] StrToByteArray(string str)
{
Dictionary<string, byte> hexindex = new Dictionary<string, byte>();
for (int i = 0; i <= 255; i++)
hexindex.Add(i.ToString("X2"), (byte)i);
List<byte> hexres = new List<byte>();
for (int i = 0; i < str.Length; i += 2)
hexres.Add(hexindex[str.Substring(i, 2)]);
return hexres.ToArray();
}