How to fast convert a string array to a byte array? - c#

I need to convert a string array to a byte array. I know this question has been posted and answered many times, but for some reason, none of the solutions work for me.
Here is the most common solution:
public static byte[] StringArrayToByteArray(string[] someStringArray)
{
return someStringArray.Select(s => Convert.ToByte(s, 16)).ToArray();
}
However, when I run this, I get the following errors: FormatException: Could not find any parsable digits. or FormatException: Additional unparsable characters are at the end of the string.
I need to save letters, along with a separator (/), for my data. Here is my code:
string[] stringArray = new string[map.Size.x * map.Size.y];
int counter = 0;
for (int y = (int) map.Rect.y; y < map.Rect.yMax; y++)
{
for (int x = (int) map.Rect.x; x < map.Rect.xMax; x++)
{
stringArray[counter] = map[x,y].Name;
stringArray[counter] += "/";
counter++;
}
}
Then I need to convert this string[] to a byte array.

You can combine those strings to a single string and return its byte[]. ie:
public static byte[] StringArrayToByteArray(string[] someStringArray)
{
return string.Join("",someStringArray).Select(x => (byte)x).ToArray();
}

The fastest way (performance-wise) to do this is to use one of the overloads of Encoding.GetBytes which allows for a supplied byte[] buffer.
This is only going to work with an encoding which is fixed width, either Unicode or ASCII. It's not clear which encoding you want. The reason you got that error is because of characters that won't fit in a byte, so I've gone with Unicode.
public static byte[] StringArrayToByteArray(string[] someStringArray)
{
var buffer = new byte[someStringArray.Sum(s => s.Length) * 2]; // remove * 2 for ASCII
var position = 0;
foreach (var s in someStringArray)
position += Encoding.Unicode.GetBytes(s, o, s.Length, buffer, position);
return buffer;
}
You can also use the new Span<byte> overload in newer versions of .NET

Related

C# Byte[Hex] Array to String - No Conversion

so I am using following Code to read from Memory:
public static extern bool ReadProcessMemory(IntPtr handle, IntPtr baseAddress, [Out] byte[] buffer, int size, out IntPtr numberOfBytesRead);
It outputs the memory Hex code as Byte Array using the code above:
buffer[0] = 01;
buffer[1] = 2D;
buffer[2] = F2;
I want to search in a certain range of the Hex Code for a certain Hex Array.
To do that I would like to use the "KMP Algorithm for Pattern Searching".
Currently I am using the following code to achieve that:
byte[] moduleBytes = {0};
IntPtr bytesRead;
ReadProcessMemory(process.Handle, baseAddress, moduleBytes, moduleBytes.Length, out bytesRead);
string buffer = "";
foreach (byte bytesfrommemory in moduleBytes)
{
buffer += bytesfrommemory.ToString("X");;
}
//algorithm
string data = buffer;
int[] value = SearchString(data, pattern);
foreach (int entry in value)
{
Console.WriteLine(entry); //Outputs the offset where it found the code
}
The issue with that is that looping trough each byte to add it to the buffer string takes ages with +1000 bytes. Is there a faster way to "convert" the byte array from array to string without actually converting it as I still need the raw byte array just as string?
I tried it with the following code, but it converts it to something different:
char[] characters = moduleBytes.Select(o => (char)o).ToArray();
string buffer = new string(characters);
Thanks for any help :)
Alexei's comment is on point; you are converting bytes to a string to run a search algorithm that will convert the string to char array (i.e. a byte array, i.e. what you started with) in order to do its work. Finding a byte array within a byte array using KMP is the same as finding a string within a string
To demonstrate my point I casted around for an implementation of KMP that works on strings. I found one at Geeks For Geeks and swapped it from working on strings, to working on bytes, literally just just editing the type in the method calls; string has a Length and can be indexed like an array, byte array has a Length and can be indexed because it is an array etc - there is no more needed to make this version work:
// C# program for implementation of KMP pattern
// searching algorithm
using System;
public class GFG {
void KMPSearch(byte[] pat, byte[] txt)
{
int M = pat.Length;
int N = txt.Length;
// create lps[] that will hold the longest
// prefix suffix values for pattern
int[] lps = new int[M];
int j = 0; // index for pat[]
// Preprocess the pattern (calculate lps[]
// array)
computeLPSArray(pat, M, lps);
int i = 0; // index for txt[]
while (i < N) {
if (pat[j] == txt[i]) {
j++;
i++;
}
if (j == M) {
Console.Write("Found pattern "
+ "at index " + (i - j));
j = lps[j - 1];
}
// mismatch after j matches
else if (i < N && pat[j] != txt[i]) {
// Do not match lps[0..lps[j-1]] characters,
// they will match anyway
if (j != 0)
j = lps[j - 1];
else
i = i + 1;
}
}
}
void computeLPSArray(byte[] pat, int M, int[] lps)
{
// length of the previous longest prefix suffix
int len = 0;
int i = 1;
lps[0] = 0; // lps[0] is always 0
// the loop calculates lps[i] for i = 1 to M-1
while (i < M) {
if (pat[i] == pat[len]) {
len++;
lps[i] = len;
i++;
}
else // (pat[i] != pat[len])
{
// This is tricky. Consider the example.
// AAACAAAA and i = 7. The idea is similar
// to search step.
if (len != 0) {
len = lps[len - 1];
// Also, note that we do not increment
// i here
}
else // if (len == 0)
{
lps[i] = len;
i++;
}
}
}
}
// Driver program to test above function
public static void Main()
{
string txt = System.Text.Encoding.ASCII.GetBytes("ABABDABACDABABCABAB");
string pat = System.Text.Encoding.ASCII.GetBytes("ABABCABAB");
new GFG().KMPSearch(pat, txt);
}
}
// This code has been contributed by Amit Khandelwal.
The biggest work (most number of keys typed) is using System.Text.Encoding.ASCII.GetBytes to get a pair of byte arrays to feed in 😀
Take away point; don't convert your memory bytes at all - convert your search term to bytes and search it in the memory bytes
Disclaimer: I offer zero guarantee that this is a correct implementation of KMP that functions adequately for your use case. It seems to work, but I'm only pointing out that you don't need to convert to strings and back again to operate code that fundamentally can search bytes in exactly the same way as it searches strings

How to convert json to hexadecimal in c#

I have json string as in example below
{"SaleToPOIRequest":{"MessageHeader":{"ProtocolVersion":"2.0","MessageClass":"Service","MessageCategory":"Login","MessageType":"Request","ServiceID":"498","SaleID":"SaleTermA","POIID":"POITerm1"},"LogoutRequest":{}}}
I want to convert json request to hexadecimal. I tried example in this link but i cannot get the exact conversion because of {,:,",} values.
Actually i can get hexadecimal return but when i reconvert to string i got return as below
{"SaleToPOIReque§7B#§²$ÖW76vTVder":{"ProtocolV¦W'6öâ#¢#"ã"Â$ÚessageClass":"Se§'f6R"Â$ÖW76vT:ategory":"Login"¢Â$ÖW76vUGR#¢*Request","Servic¤B#¢#C"Â%6ÆZID":"SaleTermA",¢%ôB#¢%ôFW&Ú1"},"LogoutReque§7B#§·×
that is not usefull for me
Is there any way to convert this?
So basically the problem is not only converting to hex but also converting back.
This is nothing more then combining 2 answers already on SO:
First for converting we use the answer given here: Convert string to hex-string in C#
Then for the converting back you can use this answer:
https://stackoverflow.com/a/724905/10608418
For you it would then look something like this:
class Program
{
static void Main(string[] args)
{
var input = "{\"SaleToPOIRequest\":{\"MessageHeader\":{\"ProtocolVersion\":\"2.0\",\"MessageClass\":\"Service\",\"MessageCategory\":\"Login\",\"MessageType\":\"Request\",\"ServiceID\":\"498\",\"SaleID\":\"SaleTermA\",\"POIID\":\"POITerm1\"},\"LogoutRequest\":{}}}";
var hex = string.Join("",
input.Select(c => String.Format("{0:X2}", Convert.ToInt32(c))));
var output = Encoding.ASCII.GetString(FromHex(hex));
Console.WriteLine($"input: {input}");
Console.WriteLine($"hex: {hex}");
Console.WriteLine($"output: {output}");
Console.ReadKey();
}
public static byte[] FromHex(string hex)
{
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
}
See it in action in a fiddle here:
https://dotnetfiddle.net/axUC5n
Hope this helps and good luck with your project
You should most probably use Encoding.Unicode to convert the string to a byte array: it's quite possible that some characters cannot be represented by ASCII chars.
Encoding.Unicode (UTF-16LE) always uses 2 bytes, so it's predictable: a sequence of 4 chars in the HEX string will always represent an UFT-16 CodePoint.
No matter what characters the input string contains.
Convert string to HEX:
string input = "Yourstring \"Ваша строка\"{あなたのひも},آپ کی تار";;
string hex = string.Concat(Encoding.Unicode.GetBytes(input).Select(b => b.ToString("X2")));
Convert back to string:
var bytes = new List<byte>();
for (int i = 0; i < hex.Length; i += 2) {
bytes.Add(byte.Parse(hex.Substring(i, 2), NumberStyles.HexNumber));
}
string original = Encoding.Unicode.GetString(bytes.ToArray());

How to convert string array to byte array in c#

So i have a string
string enc = ""hx0.+dhx0-pdhx0pzdhx0xx";
This is encrypted and when decrypted has the hexadecimal values, the starting values are
"0xfc,0xe8,0x82,0x00"
Then this
string decrypted = encryptDecrypt(enc);
then this
then i divided it after every comma to with the split command
string[] hi = decrypted.Split(',');
When i check using this code
foreach (var item in hi )
{
Console.WriteLine(item.ToString());
}
it shows all the hexadecimal in side it
i want to turn string array values which are
0xfc,0xe8,0x82,0x00 and more into byte array values which are
0xfc,0xe8,0x82,0x00 too not some other values
Is that the only string, or does that value change? Does your array need to be dynamic?
string [] arrayString = new string []; //Your Array.
byte [] arrayByte = new byte[arrayString.Length];
for (int i = 0; i < arrayString.Length; i++)
{
arrayByte[i] = Convert.ToByte(arrayString[i], 16);
}
Sample input:
String[] hi = "00,01,fe,ff".Split(',');
Conversion using a lambda function to convert each hexadecimal string to a byte:
Byte[] b = Array.ConvertAll(hi, h => Convert.ToByte(h, 16));
If you want a different kind of delegate:
Byte[] b = Array.ConvertAll(hi, HexToByte);
private Byte HexToByte(String h)
{
return Convert.ToByte(h, 16);
}
Same, with an expression-bodied function:
Byte[] b = Array.ConvertAll(hi, HexToByte);
private Byte HexToByte(String h) => Convert.ToByte(h, 16);
Or yet a different kind of delegate:
Converter<String, Byte> hexToByte = h => Convert.ToByte(h, 16);
Byte[] b = Array.ConvertAll(hi, hexToByte);
Array.ConvertAll is doing the real work. Conversion from hex is either a trivial idea that can be done inline or an important idea that can be given a name and/or a full implementation block.
Convert each of the strings into byte and then store it to str variable.
byte[,] str = new byte[50,50];
int i = 0;
foreach (var item in hi)
{
Console.WriteLine(item.ToString());
byte[] arr = Encoding.ASCII.GetBytes(item.ToString());
str[i] = arr;
i++;
}
For more information, see this link
For some text is not Ascii that you can use Utf-8 to convert string to byte.
System.Text.Encoding.UTF8.GetBytes(item);
To convert from a string to a byte array, you can use the GetBytes method:
System.Text.Encoding.ASCII.GetBytes(item);

C# - Get Integer Byte Array in String

I have a random integer value which I need to represent in String as a Byte array. For example:
int value = 32;
String strValue = getStringByteArray(value);
Console.WriteLine(strValue); // should write: " \0\0\0"
If value = 11 then getStringByteArray(value) shuld return "\v\0\0\0".
If value = 13 then getStringByteArray(value) shuld return "\r\0\0\0".
And so on.
Any idea on how to implement the method getStringByteArray(int value) in C#?
UPDATE
This is the code that receives the data from the C# NamedPipe Server:
bool CFilePipe::ReadString(int m_handle, string &value)
{
//--- check for data
if(WaitForRead(sizeof(int)))
{
ResetLastError();
int size=FileReadInteger(m_handle);
if(GetLastError()==0)
{
//--- check for data
if(WaitForRead(size))
{
value=FileReadString(m_handle,size);
return(size==StringLen(value));
}
}
}
//--- failure
return(false);
}
Don't take this approach at all. You should be writing to a binary stream of some description - and write the binary data for the length of the packet/message, followed by the message itself. For example:
BinaryWriter writer = new BinaryWriter(stream);
byte[] data = Encoding.UTF8.GetBytes(text);
writer.Write(data.Length);
writer.Write(data);
Then at the other end, you'd use:
BinaryReader reader = new BinaryReader(stream);
int length = reader.ReadInt32();
byte[] data = reader.ReadBytes(length);
string text = Encoding.UTF8.GetString(data);
No need to treat binary data as text at all.
Well. First of all you should get bytes from integer. You can do it with BitConverter:
var bytes = BitConverter.GetBytes(value);
Next, here is three variants. First - if you want to get result in binary format. Just take all your bytes and write as it is:
var str = string.Concat(bytes.Select(b => Convert.ToString(b, 2)));
Second variant. If you want convert your byte array to hexadecimal string:
var hex = BitConverter.ToString(array).Replace("-","");
Third variant. Your representation ("\v\0\0\0") - it is simple converting byte to char. Use this:
var s = bytes.Aggregate(string.Empty, (current, t) => current + Convert.ToChar(t));
This should help with that.
class Program
{
static void Main(string[] args)
{
Random rand = new Random();
int number = rand.Next(1, 1000);
byte[] intBytes = BitConverter.GetBytes(number);
string answer = "";
for (int i = 0; i < intBytes.Length; i++)
{
answer += intBytes[i] + #"\";
}
Console.WriteLine(answer);
Console.WriteLine(number);
Console.ReadKey();
}
}
Obviously, you should implement two steps to achieve the goal:
Extract bytes from the integer in the appropriate order (little-endian or big-endian, it's up to you to decide), using bit arithmetics.
Merge extracted bytes into string using the format you need.
Possible implementation:
using System;
using System.Text;
public class Test
{
public static void Main()
{
Int32 value = 5152;
byte[] bytes = new byte[4];
for (int i = 0; i < 4; i++)
{
bytes[i] = (byte)((value >> i * 8) & 0xFF);
}
StringBuilder result = new StringBuilder();
for (int i = 0; i < 4; i++)
{
result.Append("\\" + bytes[i].ToString("X2"));
}
Console.WriteLine(result);
}
}
Ideone snippet: http://ideone.com/wLloo1
I think you are saying that you want to convert each byte into a character literal, using escape sequences for the non printable characters.
After converting the integer to 4 bytes, cast to char. Then use Char.IsControl() to identify the non-printing characters. Use the printable char directly, and use a lookup table to find the corresponding escape sequence for each non-printable char.

Convert float[] to string and back to float[] - test fails, but I can't see why

The general method has been answered multiple times before, but I have a problem with my implementation which fails, and am looking to see if a kind reader can spot where I'm going wrong.
Code and test are;
[TestMethod]
public void FloatConversion()
{
// Set up some test data
int repetitions = 100000;
Random rand = new Random();
float[] testSetOfFloats = new float[repetitions];
for (int count = 0; count < repetitions; count++)
{
testSetOfFloats[count] = rand.NextFloat(0, float.MaxValue);
}
// Convert the floats into a byte array
byte[] floatsAsByteArray = new byte[repetitions * 4]; // 4 bytes for a Single
for (int count = 0; count < repetitions; count++)
{
byte[] floatAsBytes = BitConverter.GetBytes(testSetOfFloats[count]);
floatAsBytes.CopyTo(floatsAsByteArray, count * 4);
}
// Convert the byte array to a Unicode string
string serialisedByteArray = System.Text.Encoding.Unicode.GetString(floatsAsByteArray);
// ... Do some work, store the string, re-read the string, then ...
// Convert the unicode string back into a byte array
byte[] deserializedByteArray = System.Text.Encoding.Unicode.GetBytes(serialisedByteArray);
// Convert the byte array back into an array of floats
float[] deserializedFloats = new float[repetitions];
for (int count = 0; count < repetitions; count++)
{
int offset = count * 4;
deserializedFloats[count] = BitConverter.ToSingle(deserializedByteArray, offset);
}
for (int count = 0; count < repetitions; count++)
{
// This will fail - but many will pass the test.
Assert.IsTrue(deserializedFloats[count] == testSetOfFloats[count]);
}
}
The only non-standard method is an extension to Random NextFloat() which just returns a random Single from the passed range of values.
// Convert the byte array to a Unicode string
string serialisedByteArray = System.Text.Encoding.Unicode.GetString(floats);
You are converting floats to byte an then convert that to string ... a recipe for troubles.
There are certain byte Sequences (look up Surrogate pair, a high surrogate is invalid if not followed by a low surrogate and vice versa), that are not a valid UCS-2 string and therefore may not "survive" the round-trip from byte[] to string and back.
The question is therefore: Why do you convert binary data 1:1 into a string? If you need to transmit the binary as string, there are many encodings to choose from, e.g. base64.
#DasKrümelmonster's answer is correct. I want to emphasize a point though - your test was incomplete.
Had you added a test to make sure the first and second byte arrays are the same, all this would have been perfectly clear.

Categories