how can I create a byte data type from a string? For example: The device I am sending data to, expects the data to be in the hexadecimal format. More specifically, it needs to be in the format: 0x{hexa_decimal_value}
Hard coded, it already worked sending data this way.
I would create a byte array like this:
byte[] items_to_send_ = new byte[] {0x46, 0x30, 0x00};
Now I want to code it dynamically.
The code I am now trying to write looks like this:
var ListByte = new List<byte>();
foreach (char val in messageToConvert)
{
var hexa_decimal_val = Convert.ToInt32(val).ToString("X");
hexa_decimal_val = $"0x:{hexa_decimal_val}";
byte val_ = CreateByteFromStringFunction(hexa_decimal_val); // How?
ListByte.Add(val_);
}
The step in question is when creating the variable val_, where I want to build the byte value from hexa_decimal_val, but I just don't know how. Casting does not work, and I did not find any other function that would do it for me.
It feels like there should be a really easy solution to this, but I just don't seem to find it.
What makes looking for the correct answer tricky here is that I already know how to convert from string to hexadecimal value, but the conversion afterwards is nowhere to be found.
You don't need to do create bytes from characters one by one and append to a list. You can usethis;
var encodedByteList = Encoding.UTF8.GetBytes(messageToConvert);
If you still want to do that, you can do something like this;
var encodedByteList = new List<byte>();
foreach (var character in messageToConvert)
{
var correspondingByte = (byte)character;
encodedByteList.Add(correspondingByte);
}
Or with LINQ, you can use this one liner;
var encodedByteList = messageToConvert.Select(c => (byte)c);
Related
I'm working with a .NET application that stores a long list of true/false values into BitArray which gets stored in a SQL Server as a binary(32) value. The data comes back from the database as a byte[].
I'm trying to migrate the project over to Kotlin using Spring. After a lot of testing and messing around, I was finally able to get the same array in Kotlin that I do from the BitArray in C#. However, this solution seems like quite a kludge just to get an array of true/false values from a ByteArray.
I'm sure there's a cleaner way of going about this, but I'm still learning Kotlin and this is what I've come up with:
fun convertByteArrayToBitArray(array: ByteArray): List<Boolean>{
val stringBuilder = StringBuilder()
array.forEach {
// Convert to Integer to convert to binaryString
var int = it.toInt()
// Because the array has signed values, convert to unsigned value. Either this or add
// '.takeLast(8)' to the end of the String.format call
if(int < 0) int += 256
// Convert to binary string padding with leading 0s
val binary = String.format("%8s", Integer.toBinaryString(int)).replace(" ", "0")
// Through testing, this binary value needs to be reversed to give the right values
// at the right index
stringBuilder.append(binary.reversed())
}
// Convert stringBuilder to CharArray then to List of true/false values
return stringBuilder.toString().toCharArray().map {
Integer.parseInt(it.toString()) == 1
}
}
If you don't need multiplatform code, then you can use BitSet from the Java stdlib:
val bytes = byteArrayOf(0x11, 0x11)
val bits = BitSet.valueOf(bytes)
println(bits[0]) // true
println(bits[1]) // false
println(bits[4]) // true
println(bits[5]) // false
println(bits[8]) // true
println(bits[9]) // false
val bytes2 = bits.toByteArray()
It stores the data in little endian. If I read your code correctly, it also uses LE.
If you need List<Boolean> specifically, for example because some of your code already depends on it, then you can convert between BitSet and List<Boolean> like this:
fun BitSet.toBooleanList() = List(length()) { this[it] }
fun List<Boolean>.toBitSet() = BitSet(size).also { bitSet ->
forEachIndexed { i, item ->
bitSet.set(i, item)
}
}
Just note List<Boolean> is very memory-inefficient.
I am able to store the endorsement key from a TPM in a byte array using the following code (referencing TSS.NET):
TpmPublic ekPub = GetEndorsementKey();
byte[] ek = ekPub.GetTpm2BRepresentation();
I have tried this, but I don't know how to get from a Tpm2bPublicKeyRsa instance to an instance of TpmPublic:
Tpm2bPublicKeyRsa temp = new Tpm2bPublicKeyRsa(ek)
Notes:
I want to pass the endorsement key around as a byte array because it's convenient to Base64 encode the array for copy/paste.
I want to get back to an instance of TpmPublic so that I can transform that key (like this) into something I can use it server side in .NET (without a TPM) .
The solution I came up with was to use the GetTpmRepresentation method:
TpmPublic ekPub = GetEndorsementKey();
byte[] ekPubBytes = ekPub.GetTpmRepresentation();
That makes it easy to get the TpmPublic instance back using the marshaller:
var mashaller = new Marshaller(ekPubBytes);
TpmPublic ekPub = m.Get<TpmPublic>();
I'm calling a json-rpc api that returns a UCHAR array that represents a PDF file (so the result property on return contains a string representation of a UCHAR array). I need to convert this result string into a Byte array so I can handle it as a PDF file, i.e., save it and/or forward it as a file in a POST to another api.
I have tried the following (the result variable is the returned UCHAR string):
char[] pdfChar = result.ToCharArray();
byte[] pdfByte = new byte[pdfChar.Length];
for (int i = 0; i < pdfChar.Length; i++)
{
pdfByte[i] = Convert.ToByte(pdfChar[i]);
}
File.WriteAllBytes(basePath + "test.pdf", pdfByte);
I have also tried:
byte[] pdfByte = Encoding.ASCII.GetBytes(pdfObj.result);
File.WriteAllBytes(basePath + "test.pdf", pdfByte);
With both of these, when I try to open the resulting test.pdf file, it will not open, presumably because it was not converted properly.
Turns out that, although the output of the API function is UCHAR, when it comes in as part of the JSON string, it is a base64 string, so this works for me:
byte[] pdfBytes = Convert.FromBase64String(pdfObj.result);
I'm pretty sure the API is making that conversion "under the hood", i.e., while the function being called returns UCHAR, the api is using a framework to create the JSON-RPC responses, and it is likely performing the conversion before sending it out. If it is .NET that makes this conversion from UCHAR to base64, then please feel free to chime in and confirm this.
Do you know the file encoding format? Try to use this
return System.Text.Encoding.UTF8.GetString(pdfObj.result)
EDIT:
The solution you found is also reported here
var base64EncodedBytes = System.Convert.FromBase64String(pdfObj.result);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes)
I have a load of data files in numpy .npz format written from python.
I want to read them directly into C# for a few reasons.
The data files contain a number of 1D arrays of different types - some will by byte arrays, and other double arrays.
Can anyone give me some advice on how to achieve this? Or otherwise what I might be doing wrong below?
I have tried using Accord.NET.NPZFormat but can't figure out how to make it work. I think probably because you have to give it a type to return, and because the arrays are of different types it fails.
Here is a link to it:
http://accord-framework.net/docs/html/M_Accord_IO_NpzFormat_Load__1.htm
I am struggling with syntax here, unsure of what to use as "T". The closest I have got is with the following, but doesn't seem to have any data in the result. Accord.IO has no example code.
public static void LoadNPZ(string zip_file, string npz_file)
{
byte[] ret = new byte[0];
using (ZipArchive zip = ZipFile.OpenRead(zip_file))
{
foreach (ZipArchiveEntry entry in zip.Entries)
{
if (entry.Name == npz_file + ".npz")
{
Stream fs = entry.Open();
ret = new byte[fs.Length];
fs.Read(ret, 0, (int)fs.Length);
}
}
}
if (ret.Length==0)
{
return;
}
var ret2 = NpzFormat.Load<object[]>(ret);
};
You can use the NumSharp library.
Let say you have this data created in Python.
import numpy as np
arr = np.array([1,2,3,4])
single = arr.astype(np.single)
double = arr.astype(np.double)
np.savez('single.npz', data=single)
np.savez('double.npz', data=double)
The C# code to read them is below.
using NumSharp;
var singleContent = np.Load_Npz<float[]>("single.npz"); // type is NpzDictionary
var singleArray = singleContent["data.npy"]; // type is float[]
var doubleContent = np.Load_Npz<double[]>("double.npz"); // type is NpzDictionary
var doubleArray = doubleContent["data.npy"]; // type is double[]
If you don't specify name for your array then the default name is arr_0, and the C# code would be like this.
var singleArray = singleContent["arr_0.npy"];
var doubleArray = doubleContent["arr_0.npy"];
Note that NumSharp has the following limitation.
The size of each dimension must be smaller than 2,147,483,591 bytes. Example: for integer (4 bytes), each dimension must have less than 536,870,898 elements.
If you are using .NET Framework, the maximum array size is 2GB (all dimensions considered). On 64-bit platform this limit can be avoided by enabling the gcAllowVeryLargeObjects flag.
More information can be found in this answer and this blog post (Disclaimer: I'm the author of both of them).
I work with C# and python quite a bit, and my reccomendation is to create a COM Server
http://timgolden.me.uk/pywin32-docs/html/com/win32com/HTML/QuickStartServerCom.html
then in python you could simply have something like
import numpy as np
class NPtoCSharp:
_reg_clsid_ = "{7CC9F362-486D-11D1-BB48-0000E838A65F}"
_public_methods_ = ['load_file']
_public_attrs_ = ['arr', 'the_file']
_reg_desc_ = "Python NPZ Loader"
_reg_progid_ = "NPtoCSharp"
def __init__(self):
self.arr = None
self.the_file = None
def load_file(self):
self.arr = np.load(self.the_file)
return self.arr
Then in C#
public void init_python()
{
Type NPtoCSharp = Type.GetTypeFromProgID("NPtoCSharp");
NPtoCSharpInst = Activator.CreateInstance(NPtoCSharp);
NPtoCSharpInst.the_file = 'myfile.npz';
}
Not complete but I hope you get the idea.
Just to clarify something first. I am not trying to convert a byte array to a single string. I am trying to convert a byte-array to a string-array.
I am fetching some data from the clipboard using the GetClipboardData API, and then I'm copying the data from the memory as a byte array. When you're copying multiple files (hence a CF_HDROP clipboard format), I want to convert this byte array into a string array of the files copied.
Here's my code so far.
//Get pointer to clipboard data in the selected format
var clipboardDataPointer = GetClipboardData(format);
//Do a bunch of crap necessary to copy the data from the memory
//the above pointer points at to a place we can access it.
var length = GlobalSize(clipboardDataPointer);
var #lock = GlobalLock(clipboardDataPointer);
//Init a buffer which will contain the clipboard data
var buffer = new byte[(int)length];
//Copy clipboard data to buffer
Marshal.Copy(#lock, buffer, 0, (int)length);
GlobalUnlock(clipboardDataPointer);
snapshot.InsertData(format, buffer);
Now, here's my code for reading the buffer data afterwards.
var formatter = new BinaryFormatter();
using (var serializedData = new MemoryStream(buffer))
{
paths = (string[]) formatter.Deserialize(serializedData);
}
This won't work, and it'll crash with an exception saying that the stream doesn't contain a binary header. I suppose this is because it doesn't know which type to deserialize into.
I've tried looking the Marshal class through. Nothing seems of any relevance.
If the data came through the Win32 API then a string array will just be a sequence of null-terminated strings with a double-null-terminator at the end. (Note that the strings will be UTF-16, so two bytes per character). You'll basically need to pull the strings out one at a time into an array.
The method you're looking for here is Marshal.PtrToStringUni, which you should use instead of Marshal.Copy since it works on an IntPtr. It will extract a string, up to the first null character, from your IntPtr and copy it to a string.
The idea would be to continually extract a single string, then advance the IntPtr past the null byte to the start of the next string, until you run out of buffer. I have not tested this, and it could probably be improved (in particular I think there's a smarter way to detect the end of the buffer) but the basic idea would be:
var myptr = GetClipboardData(format);
var length = GlobalSize(myptr);
var result = new List<string>();
var pos = 0;
while ( pos < length )
{
var str = Marshal.PtrToStringUni(myptr);
var count = Encoding.Unicode.GetByteCount(str);
myptr = IntPtr.Add(myptr, count + 1);
pos += count + 1;
result.Add(str);
}
return result.ToArray();
(By the way: the reason your deserialization doesn't work is because serializing a string[] doesn't just write out the characters as bytes; it writes out the structure of a string array, including additional internal bits that .NET uses like the lengths, and a binary header with type information. What you're getting back from the clipboard has none of that present, so it cannot be deserialized.)
How about this:
var strings = Encoding.Unicode
.GetString(buffer)
.Split(new[] { '\0' }, StringSplitOptions.RemoveEmptyEntries);