I want to pass the following byte array through serial port.
array[j].abc = 2;
array[j].def = 4;
array[j].gh = 6;
array[j].ij = 0;
array[j].jl = 1;
array[j].fg= 1;
array[j].bh = 2;
I passed the byte array as follow
byte[] wtbin = TestSerializer.StructureToByteArray(array[j]);
byte[] bharr = new byte[1];
bharr[0] = wtbin[i];
serialPort1.Write(bharr, 0, 1);
But serialport receives it as letters like B,B etc. How can
I receive it as numbers??
You can pass a whole byte array (generally named buffer) into the serialPort.Write() method. What you are doing instead is passing a single byte to the method. In your case the call to the method would be something like:
serialport1.Write(wtbin, 0, wtbin.Length);
You can read more about SerialPort on MSDN - SerialPort Write. Additionally keep in mind that you are sending bytes, not ASCII text. Depending on what you are sending PUTTY may display different things. In order to convert a byte array(buffer) back to ASCII, you can use
Encoding.ASCII.GetString(buffer);
Hope this helps :)
Related
I'm passing int[] array that hold image, later I want to convert it to bytes[] and save the image to local path. However, I notice that the bytePic[] length is equal to int[] arrPic just the values are missing. There is a screenshot below:
Below is the entire function:
public string ChangeMaterialPicture(int[] arrPic, int materialId,string defaultPath)
{
var material = _warehouseRepository.GetMaterialById(materialId);
if(material is not null)
{
// Convert the Array to Bytes
byte[] bytePic = new byte[arrPic.Length];
for(var i = 0; i < arrPic.Length; i++)
{
AddByteToArray(bytePic, Convert.ToByte(arrPic[i]));
}
// Convert the Bytes to IMG
string filename = Guid.NewGuid().ToString() + "_.png";
System.IO.File.WriteAllBytes(#$"{defaultPath}\materials\{material.VendorId}\{filename}", bytePic);
// Update the Image
material.Picture = filename;
_warehouseRepository.UpdateMaterial(material);
return material.Picture;
}
else
{
return String.Empty;
}
}
public byte[] AddByteToArray(byte[] bArray, byte newByte)
{
byte[] newArray = new byte[bArray.Length + 1];
bArray.CopyTo(newArray, 1);
newArray[0] = newByte;
return newArray;
}
You are creating the new array newArray in AddByteToArray and return it. But at the call site you are never using this returned value and the bytePic array remains unchanged.
The code in AddByteToArray makes no sense. Why create a new array when the intention was to insert one byte into an existing array? What you need to do is to cast the int into byte. Simply write:
byte[] bytePic = new byte[arrPic.Length];
for (int i = 0; i < arrPic.Length; i++)
{
bytePic[i] = (byte)arrPic[i];
}
And delete the method AddByteToArray.
This assumes that every value in the int array is in the range 0 to 255 and therefore fits into one byte.
There are different ways to do this. With LINQ you could also write:
byte[] bytePic = arrPic.Select(i => (byte)i).ToArray();
I would assume your original array uses a int to represent a full RGBA-pixel, since 32bit per pixel mono images are very rare in my experience. And if you do have such an image, you probably want to be more intelligent in how you do this conversion. The only time just casting int to bytes would be a good idea is if you are sure only the lower 8 bits are used, but if that is the case, why are you using an int-array in the first place.
If you actually have RGBA-pixles you do not want to convert individual int-values to bytes, but rather convert a single int value to 4 bytes. And this is not that difficult to do, you just need to use the right methods. The old school options is to use Buffer.BlockCopy.
Example:
byte[] bytePic = new byte[arrPic.Length * 4];
Buffer.BlockCopy(arrPic, 0, bytePic, 0, bytePic.Length);
But if your write-method accepts a span you might want to just convert your array to a span and cast this to the right type, avoiding the copy.
I am trying to send a value by socket .So i have two parts in my project Client and server .
The client sends a value to server using this code :
System.IO.BinaryWriter binaryWriter =
new System.IO.BinaryWriter(networkStream);
binaryWriter.Write(1);
binaryWriter.Write(2);
binaryWriter.Flush();
So in other part i need to read the two values i mean 1 and 2;
So in server part i have this code :
static void Listeners()
{
Socket socketForClient = tcpListener.AcceptSocket();
if (socketForClient.Connected)
{
NetworkStream networkStream = new NetworkStream(socketForClient);
while (true)
{
List<int> variables = new List<int>();
using (var reader = new BinaryReader(networkStream))
{
for (int i = 0; i < 2; i++)
{
int t = reader.ReadInt32();
variables.Add(t);
}
}
}
}
}
As you can see i hold the values in variables list .but it doesn't work .i mean in server part i can't get the values 1 and 2 and my values is like this :841757955
best regards.
and my values is like this :841757955
Always worth sticking that number in the Windows calculator and convert that to hex. You get 0x322C3503.
Which looks a lot like ASCII, a string with 3 characters that encodes "5,2". In other words, your real code doesn't resemble your snippet at all, you don't actually use the BinaryWriter.Write(Int32) overload, you used BinaryWriter.Write(String).
Sure, that can't work, you can't write a string and expect it to be readable as raw integers. Fix your code.
As far as I can tell from your code, you are sending data as a string in binary format, this will yield bytes for the characters 1,2.
When you read the data back you try to get Int32 values.
There are two options here:
Read and write data as a string.
Client code:
binaryWriter.Write("1,2");
Server code:
string text = binaryReader.ReadString(); // "1,2"
OR Read and write data as integers.
Client code:
binaryWriter.Write(10);
binaryWriter.Write(20);
Server code:
int value1 = binaryReader.ReadInt32(); //10
int value2 = binaryReader.ReadInt32(); //20
I want to receive bytes into an array from tcp client. I've an array of bytes dataToRecieve, in which I'm receiving those bytes.
But I've got some problems here, can anyone check my code:
while (true) {
try {
Socket handler = mainSocket.Accept();
byte[] dataToRecieve = new byte[handler.ReceiveBufferSize];
int[] dataArray = new int[1024];
handler.Receive(dataToRecieve);
//////SOME CODE
int i = handler.Send(msg);
handler.Shutdown(SocketShutdown.Both);
handler.Close();
}
catch(Exception) {}
--------//////some code
Now I want to receive bytes into byte array & than convert it into the int array (however the data should be in an int array)........
Well, your code already has a problem here:
handler.Receive(dataToRecieve);
You're ignoring the value returned by Receive, to tell you how many bytes were actually read. That's almost always a bad idea. Likewise you're assuming you receive all the information you need in a single call. Usually you'd either have to loop until you'd read all the data - either by knowing that you expect a certain amount, or by reading until there is no more data.
Once you've got the data into a byte array, converting it into an integer array depends on the format in the byte array. You may be able to just use Buffer.BlockCopy, but that's only if the endianness in the byte array matches the endianness in memory. Alternatively, you can simply create an array of the right size, and write a loop:
int[] integers = new byte[size / 4];
for (int i = 0; i < integers.Length; i++)
{
integers[i] = BitConverter.ToInt32(bytes, i * 4);
}
However, again you need to consider the endianness. My MiscUtil library has an EndianBitConverter class which allows you to specify the endianness of your data.
Is there some equivalent to the StringBuilder.Insert method for use with byte arrays? I was going to try and use a MemoryStream but an error was thrown telling me that the MemoryStream object is "not expandable". I need to place bytes within specific spots of another (already existing byte array).
Here is the same idea using StringBuilder.
String firstString = "FirstData";
String someString = "string Data";
int Index = 0;
StringBuilder sb = new StringBuilder(firstString);
for(int i = 0; i < someString.Length; i++)
{
sb.Insert(index, someString[i]);
index += 2;
}
Thank you for any help,
Evan
Use a List; which will allow you to insert as needed. If you have an existing array you can call ToList().
List<byte> data1 = new List<byte>() {10, 11, 12};
List<byte> data2 = new List<byte>() {13, 14, 15};
int Index = 0;
for(int i = 0; i < data1.Count; i++)
{
data2.Insert(index, data2[i]);
index += 2;
}
Then to go back to an array simply call ToArray().
You could use a list of bytes as opposed to an array of byte and use the insert method there.
Have you tried using List, it has an Insert method
A "Stream" by definition flows only one way. There is no way to change something once it's flowed out the gate. If you want this ability, you'll have to create a regular in-memory collection of some kind to give yourself a buffer you can modify before attempting to push the data out to a stream.
You can create a byte array, instead of creating some collection of bytes:
System.Text.ASCIIEncoding encoding=new System.Text.ASCIIEncoding();
Byte[] bytes = encoding.GetBytes("yourString");
or:
byte[] utf8 = System.Text.Encoding.UTF8.GetBytes ("yourString");
Use ASCII or UTF8 or any other conversation.
I have a very painful library which, at the moment, is accepting a C# string as a way to get arrays of data; apparently, this makes marshalling for pinvokes easier.
So how do I make a ushort array into a string by bytes? I've tried:
int i;
String theOutData = "";
ushort[] theImageData = inImageData.DataArray;
//this is as slow like molasses in January
for (i = 0; i < theImageData.Length; i++) {
byte[] theBytes = System.BitConverter.GetBytes(theImageData[i]);
theOutData += String.Format("{0:d}{1:d}", theBytes[0], theBytes[1]);
}
I can do it this way, but it doesn't finish in anything remotely close to a sane amount of time.
What should I do here? Go unsafe? Go through some kind of IntPtr intermediate?
If it were a char* in C++, this would be significantly easier...
edit: the function call is
DataElement.SetByteValue(string inArray, VL Length);
where VL is a 'Value Length', a DICOM type, and the function itself is generated as a wrapper to a C++ library by SWIG. It seems that the representation chosen is string, because that can cross managed/unmanaged boundaries relatively easily, but throughout the C++ code in the project (this is GDCM), the char* is simply used as a byte buffer. So, when you want to set your image buffer pointer, in C++ it's fairly simple, but in C#, I'm stuck with this weird problem.
This is hackeration, and I know that probably the best thing is to make the SWIG library work right. I really don't know how to do that, and would rather a quick workaround on the C# side, if such exists.
P/Invoke can actually handle what you're after most of the time using StringBuilder to create writable buffers, for example see pinvoke.net on GetWindowText and related functions.
However, that aside, with data as ushort, I assume that it is encoded in UTF-16LE. If that is the case you can use Encoding.Unicode.GetString(), but that will exepect a byte array rather than a ushort array. To turn your ushorts into bytes, you can allocate a separate byte array and use Buffer.BlockCopy, something like this:
ushort[] data = new ushort[10];
for (int i = 0; i < data.Length; ++i)
data[i] = (char) ('A' + i);
string asString;
byte[] asBytes = new byte[data.Length * sizeof(ushort)];
Buffer.BlockCopy(data, 0, asBytes, 0, asBytes.Length);
asString = Encoding.Unicode.GetString(asBytes);
However, if unsafe code is OK, you have another option. Get the start of the array as a ushort*, and hard-cast it to char*, and then pass it to the string constructor, like so:
string asString;
unsafe
{
fixed (ushort *dataPtr = &data[0])
asString = new string((char *) dataPtr, 0, data.Length);
}
One thing you can do is switch from using a string to a stringBuilder it will help performance tremendously.
If you are willing to use unsafe code you can use pointers and implement the your c# code just like your c++. Or you could write a small c++\cli dll that implements this functionality.
Look into the Buffer class:
ushort[] theImageData = inImageData.DataArray;
byte[] buf = new byte[Buffer.ByteLength(theImageData)]; // 2 bytes per short
Buffer.BlockCopy(theImageData, 0, buf, 0, Buffer.ByteLength(theImageData));
string theOutData = System.Text.Encoding.ASCII.GetString(buf);
Just FYI, this has been fixed in later revision (gdcm 2.0.10). Look here:
http://gdcm.sourceforge.net/
-> http://apps.sourceforge.net/mediawiki/gdcm/index.php?title=GDCM_Release_2.0
I don't like this much, but it seems to work given the following assumptions:
1. Each ushort is an ASCII char between 0 and 127
2. (Ok, I guess there is just one assumption)
ushort[] data = inData; // The ushort array source
Byte[] bytes = new Byte[data.Length]; // Assumption - only need one byte per ushort
int i = 0;
foreach(ushort x in data) {
byte[] tmp = System.BitConverter.GetBytes(x);
bytes[i++] = tmp[0];
// Note: not using tmp[1] as all characters in 0 < x < 127 use one byte.
}
String str = Encoding.ASCII.GetString(bytes);
I'm sure there are better ways to do this, but it's all I could come up with quickly.
You can avoid unnecessary copying this way :
public static class Helpers
{
public static string ConvertToString(this ushort[] uSpan)
{
byte[] bytes = new byte[sizeof(ushort) * uSpan.Length];
for (int i = 0; i < uSpan.Length; i++)
{
Unsafe.As<byte, ushort>(ref bytes[i * 2]) = uSpan[i];
}
return Encoding.Unicode.GetString(bytes);
}
}