Remove 00 from Byte Array in C# (Encoding to String) - c#

I use a NFC-Reader to read data. The data will be stores as byte[] bytes_credentials. Receiving data is working fine but now I want to encode the 16 byte Array to String. I use string str = Encoding.Default.GetString(new_data); for decoding the array. The string output is working fine if the byte Array is fully "booked up" (16 of 16 bytes used), for example: This is an test! -> 54 68 69 73 20 69 73 20 61 6e 20 74 65 73 74 21. The problem i am facing is, that if the NFC-Array is not fully "booked up", the Array look like this: This is! -> 54 68 69 73 20 69 73 21 00 00 00 00 00 00 00 00. The output in console looks like this: This is!????????.
How can I CHECK and REMOVE the empty bytes (00) from the Array. So that the Output looks like this: This is!.
Thank you for helping!!!
I have checked previous posts but no of them are working for me...

You can use LINQ to filter your array further:
using System.Text;
var bytes_credentials = new byte[]
{
0x54,
0x68,
0x69,
0x73,
0x20,
0x69,
0x73,
0x21,
0,
0,
0,
0,
0,
0,
0,
0
};
Console.WriteLine(Encoding.Default.GetString(
bytes_credentials.Where(b => b != 0).ToArray()
));
To learn more about LINQ, take a look here: https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/linq/

Related

Bytes from string from bytes not equals origin bytes

I have an encryption algorithm (RSA) and trying to make it able to encrypt and decrypt text of any length, the problem I faced is somewhy after encryption of block of bytes, if I convert is to string (using Encoding.ASCII.GetString) and then go back (with GetBytes) - I don't get the same array of bytes, same with UTF8, I'm not really into encodings, can someone help how can I solve this problem, so I can convert encrypted bytes into string and pass it to decryption algorithm and it will get proper bytes?
byte[] bytes = new byte[] { 0xe1, 0xde, 0x4a, 0x10, 0xea, 0x74, 0x8f, 0x18, 0xd7, 0x93, 0x04, 0x7a, 0x10, 0xb2, 0xa8, 0xfa, 0x11, 0x00, 0x7a, 0xfb, 0xcb,
0x19, 0xb7, 0xf5, 0x25, 0x26, 0x6d, 0xa0, 0x0d, 0xdc, 0xe5, 0x0a };
Console.WriteLine(string.Join(" ", bytes));
// 255 222 74 16 234 116 143 24 215 147 4 122 16 178 168 250 17 0 122 251 203 25 183 245 37 38 109 160 13 220 229 10
byte[] bytes2 = Encoding.ASCII.GetBytes(Encoding.ASCII.GetString(bytes));
Console.WriteLine(string.Join(" ", bytes2));
// 63 63 74 16 63 116 63 24 63 4 122 16 63 63 63 17 0 122 63 63 25 63 63 37 38 109 63 13 63 63 10
byte[] bytes3 = Encoding.UTF8.GetBytes(Encoding.ASCII.GetString(bytes));
Console.WriteLine(string.Join(" ", bytes3));
// 63 63 74 16 63 116 63 24 63 4 122 16 63 63 63 17 0 122 63 63 25 63 63 37 38 109 63 13 63 63 10
Array bytes I got from encrypting "hello world!" with 32 bytes key from my encryption algorithm, as you see, ascii nor utf8 to string and then back to bytes doesn't gives me back my original array of bytes somewhy
You're not supposed to use the Encoding.XYZ objects for converting sequences of bytes into strings unless those bytes actually make up a string in that encoding. Their purpose is to do the bytes-to-string conversion when you're reading text from any form of medium that serves bytes, such as FileStream or similar. However, those bytes actually have to be correctly encoded for the encoding you choose. You cannot convert arbitrary sequences of bytes to strings using these encodings. As you've already observed, they will mangle the result. You might get lucky for quite a few byte sequences, but if you're using any of the cryptographic secure encryption algorithms, that luck will run out immediately.
Instead, use something like Base64 or 85. Base64 is built into .NET, and if you have this code:
byte[] original = ...
string encoded = Encoding.ASCII.GetString(original);
byte[] decoded = Encoding.ASCII.GetBytes(encoded);
all you have to do is change to this:
byte[] original = ...
string encoded = Convert.ToBase64String(original);
byte[] decoded = Convert.FromBase64String(encoded);

string to byte[] without encoding or changing actual bytes at string

assume i got the following byte[]
0C 00 21 08 01 00 00 00 86 1B 06 00 54 51 53 65 72 76 65 72
with bitconverter BitConverter.ToString i can convert it to
0C-00-21-08-01-00-00-00-86-1B-06-00-54-51-53-65-72-76-65-72
how do i convert it back from string to byte[] to get
0C 00 21 08 01 00 00 00 86 1B 06 00 54 51 53 65 72 76 65 72
ascii encoding and other methods always getting me the equivalent bytes to the string but what i really need is the string to be byte[] as it is, i know if i did a reversing operation (using getbytes then tostring) ill end up with the same string but what i care about is while at getbytes to get the exact bytes
as i said
to put
0C-00-21-08-01-00-00-00-86-1B-06-00-54-51-53-65-72-76-65-72
AS string
and get
0C 00 21 08 01 00 00 00 86 1B 06 00 54 51 53 65 72 76 65 72
As byte[]
thanks in advance
You need this
byte[] bytes = str.Split('-').Select(s => Convert.ToByte(s, 16)).ToArray();
You can use SoapHexBinary class in System.Runtime.Remoting.Metadata.W3cXsd2001 namespace
string s = "0C-00-21-08-01-00-00-00-86-1B-06-00-54-51-53-65-72-76-65-72";
byte[] buf = SoapHexBinary.Parse(s.Replace("-"," ")).Value;
Remenber that BitConverter.ToString returns an equivalent hexadecimal string representation,so
if you decide to stick with it converting back as follow:
string temp = BitConverter.ToString(buf);//buf is your array.
byte[] newbuf = temp.Split('-').Select(s => Convert.ToByte(s,16)).ToArray();
But the safest way to convert bytes to string and back is base64:
string str = Convert.ToBase64String(buf);
byte[] result = Convert.FromBase64String(str);

Encoding/Decoding hex packet

I want to send this hex packet:
00 38 60 dc 00 00 04 33 30 3c 00 00 00 20 63 62
39 62 33 61 36 37 34 64 31 36 66 32 31 39 30 64
30 34 30 63 30 39 32 66 34 66 38 38 32 62 00 06
35 2e 31 33 2e 31 00 00 02 3c
so i build the string:
string packet = "003860dc0000" + textbox1.text+ "00000020" + textbox2.text+ "0006" + textbox3.text;
then "convert" it to ascii:
conn_str = HexString2Ascii(packet);
then i send the packet... but i have this:
00 38 60 **c3 9c** 00 00 04 33 30 3c 00 00 00 20 63
62 39 62 33 61 36 37 34 64 31 36 66 32 31 39 30
64 30 34 30 63 30 39 32 66 34 66 38 38 32 62 00
06 35 2e 31 33 2e 31 00 00 02 3c **0a**
why??
Thank you!
P.S.
the function is:
private string HexString2Ascii(string hexString)
{
byte[] tmp;
int j = 0;
int lenght;
lenght=hexString.Length-2;
tmp = new byte[(hexString.Length)/2];
for (int i = 0; i <= lenght; i += 2)
{
tmp[j] =(byte)Convert.ToChar(Int32.Parse(hexString.Substring(i, 2), System.Globalization.NumberStyles.HexNumber));
j++;
}
return Encoding.GetEncoding(1252).GetString(tmp);
}
EDIT:
if i convert directly in byte, the hex packet in coded as string:
00000000 30 30 33 38 36 30 64 63 30 30 30 30 30 34 33 33 003860dc 00000433
00000010 33 30 33 43 30 30 30 30 30 30 32 30 33 34 33 32 303C0000 00203432
00000020 36 33 36 33 33 35 33 39 33 32 33 34 36 36 33 39 63633539 32346639
00000030 36 33 33 39 33 31 33 39 33 30 33 36 33 33 36 35 63393139 30363365
00000040 33 35 36 33 36 35 36 35 36 35 33 31 33 39 33 38 35636565 65313938
00000050 36 33 33 31 36 34 33 34 36 33 33 30 30 30 30 36 63316434 63300006
00000060 33 35 32 65 33 31 33 33 32 65 33 31 30 30 30 30 352e3133 2e310000
00000070 30 32 33 43 023C
You cannot convert raw binary data to string data and expect things to just work. They are not the same. This is especially true when you mix up your character encodings.
C# characters are not ASCII characters. They are Unicode characters, represented by Unicode code points. When you then turn around and write those characters out, you need to specify what kind of data to write out. When you read your byte array into a string, using Encoding.GetEncoding(1252), you are getting the characters corresponding to code page 1252, in which 0xdc is a Ü.
But when your string is being converted back into bytes to send over the network, it is being written out as UTF-8. In UTF-8, UTF-00DC cannot be encoded as a single byte, since that byte value is used to indicate the start of a multi-byte sequence. Instead, it's encoded as the multi-byte sequence 0xc3 0x9c. As far as C# is concerned, those two values are the same character. (I don't know where that extra 0x0a is coming from, but my guess is an errant line feed from one of your text boxes and/or some other part of your process).
Its not clear what exactly you're trying to do, but I suspect you are converting way too many times for it to work out correctly. If you know the byte sequence you want to send, why not just encode that as a byte[] directly? For example, use a MemoryStream and write the constant bytes you need into it.
To get the values out of your text boxes, your original code to "convert" the string of hex digits into a string of ASCII characters had the right idea. You just need to stop at the point where you have a byte array, since ultimately the byte array is what you want.
public byte[] GetBytesFrom(string hex)
{
var length = hex.Length / 2;
var result = new byte[length];
for (var i = 0; i < length; i++)
{
result[i] = byte.Parse(hex.Substring(i, 2), NumberStyles.HexNumber);
}
return result;
}
// Variable portions of packet structure.
var byte[] segment2 = GetBytesFrom(textbox1.Text);
var byte[] segment4 = GetBytesFrom(textbox2.Text);
var byte[] segment6 = GetBytesFrom(textbox3.Text);
MemoryStream output = new MemoryStream();
output.Write(new[] { 0x00, 0x38, 0x60, 0xdc, 0x00, 0x00 }, 0, 6);
output.Write(segment2, 0, segment2.Length);
output.Write(new[] { 0x00, 0x00, 0x00, 0x20 }, 0, 4);
output.Write(segment4, 0, segment4.Length);
output.Write(new[] { 0x00, 0x06 }, 0, 2);
output.Write(segment6, 0, segment6.Length);
From here, you could use MemoryStream.CopyTo() to copy it to another stream, or MemoryStream.Read() to read the entire packet into a new byte array, or MemoryStream.GetBuffer() to get the underlying buffer (though that last one is rarely what you want -- it includes unused padding bytes)

Object-to-bytes conversion

When I'm trying to convert an object into byte array I'm getting a wierd array.
this is the code:
using (MemoryStream ms = new MemoryStream())
{
BinaryFormatter bf = new BinaryFormatter();
bf.Serialize(ms, obj);
Console.WriteLine(ByteArrayToString(ms.ToArray()));
}
//int obj = 50;
//string ByteArrayToString(byte[] byteArr) the functionality of this method is pretty obvious
the result is this:
"00 01 00 00 00 FF FF FF FF 01 00 00 00 00 00 00 00 04 01 00 00 00 0C 53 79 73 74 65 6D 2E 49 6E 74 33 32 01 00 00 00 07 6D 5F 76 61 6C 75 65 00 08 32 00 00 00 0B "
Can somebody explain to me WHY?:) the optimal result should be only "32 00 00 00".
Since serializer needs to provide enough information to deserialize the data back, it must include some metadata about the object being serialized. Specifically, the
53 79 73 74 65 6D 2E 49 6E 74 33 32
part stands for System.Int32
If you use BinaryWriter and its Write(Int32) method instead, you'll get the desired effect: your memory stream will contain just the four bytes from your integer. You wouldn't be able to deserialize it without knowing that you wrote an Int32 into the stream.
You're conflating BinaryFormatter serialization with an object's in memory format. What is written to the stream is merely an implementation detail of the BinaryFormatter and should not be relied upon for any interprocess communication not using BinaryFormatter.
If you're looking for the byte representation of the built-in types, use BitConverter.GetBytes (for strings use the appropriate Encoding.GetBytes).
The serialized byte array has both the data itself and the type info. That's why you get more info than you expect. That's neccessary for later deserializing.
The extra stuff in the results would be the BinaryFormatter object. You're not just outputting int obj = 50, you're outputting everything included in the BinaryFormatter as well.
Serialization process uses extra bytes to store information about types - it's the only way to ensure that serialized data will be deserialized into same objects of same types.
If you absolutely sure in what you doing and want to avoid any extra bytes, you may use your own serialization and make your formatter and serializers, which is very complicated. Or, you could use marshalling:
var size = Marshal.SizeOf(your_object);
// Both managed and unmanaged buffers required.
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
// Copy object byte-to-byte to unmanaged memory.
Marshal.StructureToPtr(font.LogFont, ptr, false);
// Copy data from unmanaged memory to managed buffer.
Marshal.Copy(ptr, bytes, 0, size);
// Release unmanaged memory.
Marshal.FreeHGlobal(ptr);
And to convert bytes to object:
var bytes = new byte[size];
var ptr = Marshal.AllocHGlobal(size);
Marshal.Copy(bytes, 0, ptr, size);
var your_object = (YourType)Marshal.PtrToStructure(ptr, typeof(YourType));
Marshal.FreeHGlobal(ptr);
This is quite slow and unsafe to use in most cases, but it's easiest way to strictly convert object to byte[] without implementing serialization and without [Serializable] attribute.

To read the hex value of a .txt file in c#

If I have some text file like abc.txt the I want to the hex value of that .txt file
like we see when we open notepad+ can click on hex...something like this
74 68 65 72 77 69 73 65 20 69 73 20 69 74 63 68
therwise is itch
69 6e 27 20 66 6f 72 20 61 20 66 69 67 68 74 2e
in' for a fight.
Now i want these hex values of individual letters.
I know how to read text by using FileStream() and StreamReader().
But now want these hex values how can i get this?
BinaryReader reader = new BinaryReader(new FileStream("C:\\file.ext", FileMode.Open, FileAccess.Read, FileShare.None));
reader.BaseStream.Position = 0x0; // The offset you are reading the data from
byte[] data = reader.ReadBytes(0x10); // Read 16 bytes into an array
reader.Close();
So assuming the input is therwise is itch:
string data_as_str = Encoding.Default.GetString(data); // Output: therwise is itch
string data_as_hex = BitConverter.ToString(data); // Output: 74-68-65-72-77-69-73-65-20-69-73-20-69-74-63-68
Open using FileStream, then use Read to get arrays of byte. For each element in the array convert to a hex pair with byteVal.ToString("x2") (use X2 if you want uppercase hex).

Categories