Say I have two byte arrays.
In the first scenario, I concatenate the two arrays (using Buffer.BlockCopy), then convert the result to base64 string.
In the second scenario, I convert each byte array into base64 string and then concatenate those strings.
Would the two results be the same?
Results would be the same if length of the first array is divisible by 3, in all other cases result of concatenation of two base64 strings would be different (and invalid base64) due to padding bytes at the end of first string. Length of second array does not matter for this operation as padding is always at the end.
Why "divisible by 3" - since base64 encodes every 3 bytes into exactly 4 characters arrays of such length will not need padding at the end. See https://www.rfc-editor.org/rfc/rfc4648#section-4 for formal details and https://en.wikipedia.org/wiki/Base64#Padding for more readable explanation.
I.e. if first array is 4 bytes long you get == at the end of converted string and concatenation with other base64 string will result in invalid base64 text
Convert.ToBase64String(new byte[]{1,2,3,4}) // AQIDBA==
Sample case where concatenation works the same on arrays first or on strings:
Convert.ToBase64String(new byte[]{1,2,3}) + // length divisible by 3
Convert.ToBase64String(new byte[]{4,5})
==
Convert.ToBase64String(new byte[]{1,2,3,4,5}) // AQIDBAU=
void Main()
{
byte[] bytes1 = new byte[]{10, 20, 30, 40, 0, 0, 0, 0};
byte[] bytes2 = new byte[]{50, 60, 70, 80};
Buffer.BlockCopy(bytes2, 0, bytes1, 4, 4);
PrintByteArray(bytes1);
string bytesStr = Convert.ToBase64String(bytes1);
Console.WriteLine(bytesStr);
string bytesStr1 = Convert.ToBase64String(bytes1);
string bytesStr2 = Convert.ToBase64String(bytes2);
string bytesStrMerged = bytesStr1 + bytesStr2;
Console.WriteLine(bytesStrMerged);
}
public void PrintByteArray(byte[] bytes)
{
var sb = new StringBuilder();
foreach (var b in bytes)
{
sb.Append(b + " ");
}
Console.WriteLine(sb.ToString());
}
Outputs:
10 20 30 40 50 60 70 80
ChQeKDI8RlA=
ChQeKDI8RlA=MjxGUA==
Related
I have a string stream and a byte array:
string stream = "0X210X010X030X020X220X2A0XF10XFF0X010X010X030X02";
byte[] pattern = { 0X01, 0X03, 0X02 };
I want to find all the indexes based on bytes of this pattern in the stream (in this example 1 and 9).
Then two bytes are added after each pattern to show the pattern number.
For the first pattern:0X000X00
For the second pattern:0X010X00
My expected result is indixes 1 and 9 also the output string:
0X210X010X030X020X000X000X220X2A0XF10XFF0X010X010X030X020X010X00
My code is as follows:
string stream = "0X210X010X030X020X220X2A0XF10XFF0X010X010X030X02";
byte[] pattern = { 0X01, 0X03, 0X02 };
var arrayOfStream= stream.Split(new string[] { "0X" }, StringSplitOptions.None);
arrayOfStream = arrayOfStream.Where(x => !string.IsNullOrEmpty(x)).ToArray();
List<int> indexOfPattern = new List<int>();
for (int i = 0; i < arrayOfStream.Length - 2; i++)
if (arrayOfStream[i] == pattern[0].ToString("00") &&
arrayOfStream[i+1] == pattern[1].ToString("00") &&
arrayOfStream[i+2] == pattern[2].ToString("00") )
indexOfPattern.Add(i);
I could only find indexes 1 and 9. But how to add a two-byte number to the stream. My code only works for patterns with length 3. I want it to work for patterns with different lengths. please help
1-Instead of converting the input stream to an array, you can convert the pattern to a stringusing BitConverter.ToString()
2- Then get all pattern indexes by using Regex.Matches()
3- Because the indexes are based on characters, and you want based on bytes, we have to divide the indexes by 4.(ex: 0X00 is four characters)
4- Using BitConverter.GetBytes() convert the pattern number into a two-byte array.(If we used int, it would be 4 bytes, short was used to be 2 bytes). According to what was said in part 1. We convert this byte array to a string.
5- using String.Insert(Int32, String) add insertString after the pattern. every number that is added, we must add 8 to the offset(0X000X00 is 8 characters)
List<int> indexOfPattern = new List<int>();
//1
string hexPattern = "0X"+ BitConverter.ToString(pattern).Replace("-", "0X"); //0X010X030X02
//2
Regex regex = new Regex(hexPattern);
var matches = regex.Matches(stream);
for (short i = 0; i < matches.Count; i++)
{
indexOfPattern.Add(matches[i].Index/4); //3
var temp = BitConverter.GetBytes(i); //4
string insertString = "0X" + BitConverter.ToString(temp).Replace("-", "0X");
stream= stream.Insert(matches[i].Index+hexPattern.Length + (i) * 8, insertString); //5
}
result:
stream ==>
0X210X010X030X020X000X000X220X2A0XF10XFF0X010X010X030X020X010X00
indexOfPattern==> 1 and 9
So someone took int value, converted it to string then converted it to ASCII values and then finally to byte[] with inconsistent length 1 - 4 bytes.
e.g. 100 -> "100" -> { 49, 48, 48 }.
Now I need that int value and I did it like this:
{ 49, 48, 48 } -> '1' + '0' + '0' -> "100" -> 100
switch (header[25].Count)
{
case 1:
hex = "" + (char)header[25][0];
amountOfData = Convert.ToInt32(hex, 16);
break;
case 2:
hex = "" + (char)header[25][0] + (char)header[25][1];
amountOfData = Convert.ToInt32(hex, 16);
break;
case 3:
hex = "" + (char)header[25][0] + (char)header[25][1] + (char)header[25][2];
amountOfData = Convert.ToInt32(hex, 16);
break;
case 4:
hex = "" + (char)header[25][0] + (char)header[25][1] + (char)header[25][2] + (char)header[25][3];
amountOfData = Convert.ToInt32(hex, 16); ;
break;
default:
break;
}
but maybe there is better solution...
EDIT: sorry for not mentioning that, but header is List<List<byte>>
You can use the Encoding/GetString method to convert bytes of different encodings (e.g. ASCII in your case) to a .NET string:
var input = new byte[] { 49, 48, 48 };
var str = Encoding.ASCII.GetString(input);
var result = int.Parse(str, NumberStyles.None, CultureInfo.InvariantCulture);
You can use library functions to parse from byte-like data to primitives; you're talking about ASCII, which means that Utf8Parser will work fine for us (all ASCII is also valid UTF8, although the reverse is obviously not true); normally, we would expect that header[25] is a byte[], a segment there-of, or some other raw binary source, but: ultimately, something like:
var span = new ReadOnlySpan<byte>(header[25], 0, header[25].Count);
if (!Utf8Parser.TryParse(span, out int amountOfData, out _))
ThrowSomeError(); // not an integer
If header[25] is something less convenient (like a List<byte> - I notice that in your example, your header[25] has a .Count not a .Length, which suggests it isn't a byte[]), then you can always either stackalloc a local buffer and copy the data out, or you can peek inside the list with CollectionMarshal.AsSpan<T>(List<T>), which returns a Span<T> from the underlying data:
var span = CollectionMarshal.AsSpan(header[25]);
if (!Utf8Parser.TryParse(span, out int amountOfData, out _))
ThrowSomeError(); // not an integer
As a runnable example that just shows the API:
using System;
using System.Buffers.Text;
Span<byte> span = stackalloc byte[] { 49, 48, 48 };
if (!Utf8Parser.TryParse(span, out int amountOfData, out _))
throw new FormatException();
Console.WriteLine(amountOfData); // 100
I have a byte array:
newMsg.DATA = new byte[64];
How can I convert it into binary value and then write it in text file with comma separation. Comma should be in between binary values not bytes.....
like 1,1,1,0,0,0,1,1,1,1,1,0,0,0,0,0.......
Here is an example that uses LINQ:
byte[] arr = new byte[] { 11, 55, 255, 188, 99, 22, 31, 43, 25, 122 };
string[] result = arr.Select(x => string.Join(",", Convert.ToString(x, 2)
.PadLeft(8, '0').ToCharArray())).ToArray();
System.IO.File.WriteAllLines(#"D:\myFile.txt", result);
Every number in byte[] arr is converted to a binary number with Convert.ToString(x, 2) and the comma "," is added between binary values with string.Join(",",...). At the end you can write all the elements in result to a text file by using System.IO.File.WriteAllLines.
The example above gives you this kind of output in a txt file:
0,0,0,0,1,0,1,1
0,0,1,1,0,1,1,1
1,1,1,1,1,1,1,1
...
Explanation of Convert.ToString(value, baseValue):
The first parameter value represents the number you want to convert to a string
and the second parameter baseValue represents which type of conversion you want to perform.
Posible baseValues are : 2,8,10 and 16.
BaseValue = 2 - represents a conversion to a binary number representation.
BaseValue = 8 - represents a conversion to a octal number representation.
BaseValue = 10 - represents a conversion to a decimal number representation.
BaseValue = 16 - represents a conversion to a hexadecimal number representation.
I think this will Help you c# provides inbuilt functionality to do so
with help of Convert.ToString(byte[],base); here base could be[2(binary),8(octal),16(HexaDecimal)]
byte[] data = new byte[64];
// 2nd parameter 2 is Base e.g.(binary)
string a = Convert.ToString(data[data.Length], 2);
StringBuilder sb = new StringBuilder();
foreach(char ch in a.ToCharArray())
{
sb.Append(ch+",");
}
// This is to remove last extra ,
string ans = sb.ToString().Remove(sb.Length - 1, 1);
This should get you going:
var bytes = new byte[] { 128, 255, 2 };
var stringBuilder = new StringBuilder();
for (var index = 0; index < bytes.Length; index++)
{
var binary = Convert.ToString(bytes[index], 2).PadLeft(8, '0');
var str = string.Join(",", binary.ToCharArray());
stringBuilder.Append(str);
if (index != bytes.Length -1) stringBuilder.Append(",");
}
Console.WriteLine(stringBuilder);
i do have an byte array included a range of numbers...
t Block and not the rest!
How can i have all block 4-8 in Temp[] ??
Elements 4-8 (or in reality index 3-7) is 5 bytes. Not 4.
You have the source offset and count mixed up:
Buffer.BlockCopy(bResponse, 3, temp, 0, 5);
Now temp will contain [23232].
If you want the last 4 bytes then use this:
Buffer.BlockCopy(bResponse, 4, temp, 0, 4);
Now temp will contain [3232].
To convert this to an int:
if (BitConverter.IsLittleEndian)
Array.Reverse(temp);
int i = BitConverter.ToInt32(temp, 0);
Edit: (After your comment that [43323232] actually is {43, 32, 32, 32})
var firstByte = temp[0]; // This is 43
var secondByte = temp[1]; // This is 32
var thirdByte = temp[2]; // 32
var fourthByte = temp[3]; // 32
If you want to convert this to an int then the BitConverter example above still works.
i have exception when i run this code ,, what is wrong
var encoder = new System.Text.UTF8Encoding();
System.Text.Decoder utf8Decode = encoder.GetDecoder();
byte[] todecodeByte = Convert.FromBase64String(encodedMsg);
int charCount = utf8Decode.GetCharCount(todecodeByte, 0, todecodeByte.Length);
var decodedChar = new char[charCount];
utf8Decode.GetChars(todecodeByte, 0, todecodeByte.Length, decodedChar, 0);
var message = new String(decodedChar);
exception occurs in this line
byte[] todecodeByte = Convert.FromBase64String(encodedMsg);
Base64 encoding encodes 6 bits per character. So the length of the string, multiplied by 6, must be divisible by 8. If it is not then it doesn't have enough bits to fill every byte and you'll get this exception.
So good odds that encodedMsg just isn't a properly encoded base64 string. You can append some = characters to bypass the exception and see if anything recognizable pops out. The = character is the padding character for base64:
while ((encodedMsg.Length * 6) % 8 != 0) encodedMsg += "=";
// etc...