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();
}
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 want to convert a string ("00812B1FA4BEA310199D6E00DD010F5402000001807") to a byte array.
But I want each digit of the string to be the hex value.
Expected result:
array[0] = 0x00;
array[1] = 0x81;
array[0] = 0x2B;
array[0] = 0x1F;
etc...
I tried several methods. None gave the expected result. The closest ones were:
private static byte[] Convert(string tt)
{
byte[] bytes2 = new byte[tt.Length];
int i = 0;
foreach ( char c in tt)
{
bytes2[i++] = (byte)((int)c - 48);
}
return bytes2;
}
public static byte[] ConvertHexStringToByteArray(string hexString)
{
byte[] HexAsBytes = new byte[hexString.Length / 2];
for (int index = 0; index < HexAsBytes.Length; index++)
{
string byteValue = hexString.Substring(index * 2, 2);
byte[] a = GetBytes(byteValue);
HexAsBytes[index] = a[0];
}
return HexAsBytes;
}
Found solution here: How do you convert Byte Array to Hexadecimal String, and vice versa?
( answer starting by Inverse function for Waleed Eissa code)
Difficult to find because the thread has 36 answers.
public static byte[] HexToBytes(string hexString)
{
byte[] b = new byte[hexString.Length / 2];
char c;
for (int i = 0; i < hexString.Length / 2; i++)
{
c = hexString[i * 2];
b[i] = (byte)((c < 0x40 ? c - 0x30 : (c < 0x47 ? c - 0x37 : c - 0x57)) << 4);
c = hexString[i * 2 + 1];
b[i] += (byte)(c < 0x40 ? c - 0x30 : (c < 0x47 ? c - 0x37 : c - 0x57));
}
return b;
}
You can use Convert.ToByte to convert 2 hexadecimal chars to byte.
public static byte[] HexToByteArray(string hexstring)
{
var bytes = new List<byte>();
for (int i = 0; i < hexstring.Length/2; i++)
bytes.Add(Convert.ToByte("" + hexstring[i*2] + hexstring[i*2 + 1], 16));
return bytes.ToArray();
}
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
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;
}
How do you convert a string such as "01110100011001010111001101110100" to a byte array then used File.WriteAllBytes such that the exact binary string is the binary of the file. In this case it would be the the text "test".
In case you don't have this LINQ fetish, so common lately, you can try the normal way
string input ....
int numOfBytes = input.Length / 8;
byte[] bytes = new byte[numOfBytes];
for(int i = 0; i < numOfBytes; ++i)
{
bytes[i] = Convert.ToByte(input.Substring(8 * i, 8), 2);
}
File.WriteAllBytes(fileName, bytes);
LINQ is great but there must be some limits.
You could start by splitting the string into a sequence of 8-character strings, then convert those strings to bytes, and eventually write the bytes to a file
string input = "01110100011001010111001101110100";
var bytesAsStrings =
input.Select((c, i) => new { Char = c, Index = i })
.GroupBy(x => x.Index / 8)
.Select(g => new string(g.Select(x => x.Char).ToArray()));
byte[] bytes = bytesAsStrings.Select(s => Convert.ToByte(s, 2)).ToArray();
File.WriteAllBytes(fileName, bytes);
EDIT: here's another way to split the string into 8-character chunks, perhaps a bit simpler :
int nBytes = (int)Math.Ceiling(input.Length / 8m);
var bytesAsStrings =
Enumerable.Range(0, nBytes)
.Select(i => input.Substring(8 * i, Math.Min(8, input.Length - 8 * i)));
If you know that the length of the string is a multiple of 8, you can make it even simpler :
int nBytes = input.Length / 8;
var bytesAsStrings =
Enumerable.Range(0, nBytes)
.Select(i => input.Substring(8 * i, 8));
A bit late, but here's my 2 cents:
var binaryStr = "01110100011001010111001101110100";
var byteArray = Enumerable.Range(0, int.MaxValue/8)
.Select(i => i*8)
.TakeWhile(i => i < binaryStr.Length)
.Select(i => binaryStr.Substring(i, 8))
.Select(s => Convert.ToByte(s, 2))
.ToArray();
File.WriteAllBytes("C:\temp\test.txt", byteArray);
Actually the answer by #Maciej is not correct. As #Phate01 noticed the numOfBytes is correct only for input length which is a power of 8. The second thing is that the byte array should be populated from n to 0 index not the opposite way. Here's the code example:
var bits = "000011110000001000";
var numOfBytes = (int)Math.Ceiling(bits.Length / 8m);
var bytes = new byte[numOfBytes];
var chunkSize = 8;
for (int i = 1; i <= numOfBytes; i++)
{
var startIndex = bits.Length - 8 * i;
if (startIndex < 0)
{
chunkSize = 8 + startIndex;
startIndex = 0;
}
bytes[numOfBytes - i] = Convert.ToByte(bits.Substring(startIndex, chunkSize), 2);
}
This can be improved to get rid of the if statetment but in this form it's more understandable.
The other answers have you covered, but just for fun I wrote the opposite. Going from the string to the ascii binary representation:
private static string StringToAsciiBin(string s)
{
string output = "";
foreach (char c in s.ToCharArray())
{
for (int i = 128; i >= 1; i /=2)
{
if (((int)c & i) > 0)
{
output += "1";
}
else
{
output += "0";
}
}
}
return output;
}