I am trying to reproduce the following statement in C#. As the procedure shows, packlength is a string packed according to the '!l' format which represents a long value (in network byte order - big endian).
packlength=struct.pack('!l', len(packetdata)+10)
I attempted the following:
using (MemoryStream stream = new MemoryStream()) {
using (BinaryWriter writer = new BinaryWriter(stream)) {
writer.Write ((long)(packetData.Length+10));
}
}
Is the procedure correct? If so, how do I access the resulted "string" from the memory stream?
You can use this code:
byte[] bytes = BitConverter.GetBytes(
IPAddress.HostToNetworkOrder((long)packetdata.length + 10)
);
This reads rather badly so you way wish to wrap IPAddress.HostToNetworkOrder in a different class, as a static method, to improve feasibility. After all, who wants to see IPAddress when doing a host to network order conversion?
Although your Python code is using strings to hold the buffer, they are not really strings. Why you have here is a byte array and that's what the code above produces.
C# equivalent is
var bytes=BitConverter.GetBytes((long)packetdata.length)
UPDATE:
John skeet have a very good lib for playing with byte order.check out the following link
http://www.yoda.arachsys.com/csharp/miscutil/
Related
I'm making a chat system thing with tcp which requires to send things in byte arrays, but when I convert an image into a byte array, send it and then convert back it gives this error: 'End of Stream encountered before parsing was completed.'. With strings it works just fine.
public byte[] ObjectToByteArray(object obj)
{
BinaryFormatter formatter = new BinaryFormatter();
using (var stream = new MemoryStream())
{
formatter.Serialize(stream, obj);
return stream.ToArray();
}
}
public object ByteArrayToObject(byte[] bytes)
{
using (var stream = new MemoryStream())
{
var binForm = new BinaryFormatter();
stream.Write(bytes, 0, bytes.Length);
stream.Position = 0;
var obj = binForm.Deserialize(stream);
return obj;
}
}
There's two separate things here; firstly, and I cannot emphasize this enough; do not use BinaryFormatter. Ever. It will hurt you. Lots of serializers exist, and BinaryFormatter (and the cousin NetDataContractSerializer) is literally the absolute last you should use. I can expand on that if you like, or I can suggest alternatives if you like.
Now; as for the actual problem: I strongly suspect that it isn't what you think it is. I have a hunch, based on decades of working on network code, that the real problem here is "framing". By which I mean: TCP is a stream protocol, not a message/packet protocol. I strongly suspect that you have not correctly deframed the exact bytes that were sent. I can't say this for sure without seeing your socket code, but... as I say: it is an hunch based on lots of experience. To investigate this: note the length of the bytes you send, and note the length of the bytes you've received. I'm pretty sure you'll find they are different. If there's still doubt: get the base-64 or hex string of the sent payload and the received payload (Convert.ToBase64String, for example), and compare that string. I'm pretty sure they'll turn out to be different.
Ultimately, network code is hard; I could try and explain individual points, but "how to correctly send messages over a network" could fill a book. IMO, if you're not interested in specializing in writing network code for the next 5 years: use an existing tool that will do the job for you, for example gRPC. Lots and lots of other messaging RPC tools exist.
I am trying to figure out how to work with protobuf-net. The below example is trivial on purpose. It does not reflect a real life application.
Please, observe:
var ms = new MemoryStream();
Serializer.Serialize(ms, 1234);
Serializer.Serialize(ms, 5678);
ms.Position = 0;
var n1 = Serializer.Deserialize<int>(ms);
var n2 = Serializer.Deserialize<int>(ms);
Debug.WriteLine(n1);
Debug.WriteLine(n2);
It outputs:
5678
0
What is wrong?
I am using protobuf-net 2.4.0
As said in the comments, Protobuf doesn't have a concept of 'packets' the way you'd expect. A stream is always fully read on deserialization, previously read values are overriden when they're seen again in the stream. Therefore, writing multiple messages to a single stream won't work the way you do it. Unfortunately, there is no easy fix, you have to implement packet-splitting yourself. One way to do it is to prefix any message by it's length, and split the input accordingly. This works good for bigger message, but your message consists only of a single int which would scale very badly. I'd really suggest not using protobuf at all in this scenario, instead you could take a look at their int-serialization routine (some dynamic-length encoding if I remember correctly) and serialize and deserialize single ints yourself.
You can use BitConverter for converting integers to byte arrays and then sending the arrays to memorystream:
Following link can help:
https://www.c-sharpcorner.com/uploadfile/mahesh/convert-integer-to-byte-array-in-C-Sharp/
then once you have the array of bytearrays, you can do this:
var memoryStream = new MemoryStream();
for(int temp = 0; temp < bytArray.Length; temp++)
memoryStream.Write(byteArray[temp], 0, byteArray[temp].Length);
Finally, use Protobuff to have memorystream.
I have a float array :
float[] samples32array
I need to convert it into a binary file so I can read it in matlab.
Is there any way to do that?
It's simple. First, you should use FileStream and create a file. Then, you can use BinaryWriter, which can write any C# datatype into an underlaying stream, such as a FileStream.
using (FileStream file = File.Create(path))
{
using (BinaryWriter writer = new BinaryWriter(file))
{
foreach (float value in samples32array)
{
writer.Write(value);
}
}
}
Since the constructor of BinaryWriter accepts the basic type Stream, any stream type can be used. It works for file streams as well as NetworkStream or a MemoryStream etc. It's a very generic class.
And please avoid converting the float[] into a byte[] beforehand as it will allocate memory and this is bad if your array is big (don't know if that's the case for you).
You can use BinaryWriter to write the data to a file very easily:
foreach (var value in samples32array)
{
writer.Write(value);
}
Now BinaryWriter is guaranteed to use little-endian format, so in your Matlab call, you should specify a machinefmt value of l to explicitly read it in little-endian format too.
This SO answer shows a way to convert a float array into a byte array. Then you can use File.WriteAllBytes() method to write it out to a file. How MatLab reads it, though, will be the issue.
I found some documentation for MatLab for the fread command. It looks like is has some arguments that will allow you to define the precision of the read. You may be able to use "float" as the precision value. Though, the is a bit of an educated guess as I am not very familiar with MatLab.
I'm seriously stuck in this problem.
this problem caused because i'm weak with C# concept.
all i want do is electronic equipment return gif format data. which is binary i believe.
so i want convert this data to image.
/// below is just send command to instrument that i want " Returns an image of the display in .gif format "
my6705B.WriteString("hcop:sdump:data?", true);
string image_format = my6705B.ReadString();
So i received gif data from instrument, manual said this is " Returns an image of the display in .gif format " ==> I believe this is binary format.
below link is what's in side in string image_format.
string image_format
http://i.stack.imgur.com/UcYqV.png
my goal is convert this string to image file. (png or jpg whatever)
so i convert this string variable to byte array.
below is my code after this command ....
//// this also couldn't work ~~~
System.Text.UnicodeEncoding encode = new System.Text.UnicodeEncoding();
byte[] byte_array22 = encode.GetBytes(image_format);
MemoryStream ms4 = new MemoryStream(byte_array22);
Image image = Image.FromStream(ms4); //// error point
image.Save(#"C:\Users\Administrator\Desktop\imageTest.png");
//// this also couldn't work ~~~
byte[] byte_array22 = Encoding.Unicode.GetBytes(image_format);
MemoryStream ms4 = new MemoryStream(byte_array22);
Image image = Image.FromStream(ms4, true, true); /// always error here,,,
image.Save(#"C:\Users\Administrator\Desktop\imageTest.png", System.Drawing.Imaging.ImageFormat.Png);
both code didn't work and error point is same. i commented error point.
and anyway string to byte array is work.
I'm pain with this problem several days.
but my vendor make this code with C++,, this is working .
let me share my vendor's code,.this is implemented C++.
char szReadBuffer[102400] = {'\0', };
char szReadBinary[102400] = {'\0', };
m_iStatus = viOpenDefaultRM(&m_vDefaultRM);
m_iStatus = viOpen(m_vDefaultRM, (LPSTR)(LPCTSTR)m_strVISA, VI_NULL, VI_NULL, (ViPSession)&m_iDevHandle);
m_iStatus = viSetAttribute(m_iDevHandle, VI_ATTR_TMO_VALUE, 15000);
m_iStatus = QueryGPIB("HCOPy:SDUMp:DATA?", szReadBuffer, sizeof(szReadBuffer));
//Store the results in a text file
CFile file;
file.Open("PICTURE.GIF", CFile::modeReadWrite | CFile::modeCreate | CFile::typeBinary);
memcpy(szReadBinary, &szReadBuffer[2], sizeof(szReadBuffer));
file.Write(szReadBinary, sizeof(szReadBinary));
file.Close();
i think important point is what they declare. they declare char[] .
and adviced me that this C++ code did use String MultiByte ? (just hear from him)
i have no exp with C++.
and if i follow this c++ code then working.
my goal is implement with C#. so need to follow C++ code.
please advice my problem.
It can be confusing sometimes to port C++ to C# if you're unfamiliar with one or the other (never mind both! :) ). One thing to keep in mind: there's no "byte" type in C++. Instead, binary data is stored in char[] arrays, just like C strings.
On the other hand, C# distinguishes between the two. So when you see a char[] in C++ that's being used to store binary data instead of character data, the C# equivalent is a byte[], not a char[] or System.String as it might be for other C++ usages of char[].
Your "my6705B" object appears to be some kind of abstraction of your hardware device. Presumably in addition to the WriteString() and ReadString() methods, there are methods that can be used to write and read binary data, using a byte[] type instead of characters or strings. Use that instead.
Let's assume the proper method is named "ReadBytes()". Then your code would look like this:
byte[] image_format = my6705B.ReadBytes();
MemoryStream ms4 = new MemoryStream(image_format);
Image image = Image.FromStream(ms4);
image.Save(#"C:\Users\Administrator\Desktop\imageTest.png");
Now, that may or may not be exactly what you need. You haven't provided enough information about the "my6705B" object. Many I/O APIs allow for partial reads of available data, so it's possible you would need to read from the device in a loop until you know (somehow) that you've received all of the available bytes for the image. Or maybe the type you're using for the "my6705B" object handles that all for you. I have no way to know…you'll have to figure that out yourself.
But hopefully the above gets you oriented enough wrt the C++ vs C# issues to get you a little further.
This question already has answers here:
C# - How do I read and write a binary file?
(4 answers)
Closed 9 years ago.
The application I'm attempting to create would read the binary code of any file and create a file with the exact same binary code, creating a copy.
While writing a program that reads a file and writes it somewhere else, I was running into encoding issues, so I hypothesize that reading as straight binary will overcome this.
The file being read into the application is important, as after I get this to work I will add additional functionality to search within or manipulate the file's data as it is read.
Update:
I'd like to thank everyone that took the time to answer, I now have a working solution. Wolfwyrd's answer was exactly what I needed.
BinaryReader will handle reading the file into a byte buffer. BinaryWriter will handle dumping those bytes back out to another file. Your code will be something like:
using (var binReader = new System.IO.BinaryReader(System.IO.File.OpenRead("PATHIN")))
using (var binWriter = new System.IO.BinaryWriter(System.IO.File.OpenWrite("PATHOUT")))
{
byte[] buffer = new byte[512];
while (binReader.Read(buffer, 0, 512) != 0)
{
binWriter.Write(buffer);
}
}
Here we cycle a buffer of 512 bytes and immediately write it out to the other file. You would need to choose sensible sizes for your own buffer (there's nothing stopping you reading the entire file if it's reasonably sized). As you mentioned doing pattern matching you will need to consider the case where a pattern overlaps a buffered read if you do not load the whole file into a single byte array.
This SO Question has more details on best practices on reading large files.
Look at MemoryStream and BinaryReader/BinaryWriter:
http://www.dotnetperls.com/memorystream
http://msdn.microsoft.com/en-us/library/system.io.binaryreader.aspx
http://msdn.microsoft.com/en-us/library/system.io.binarywriter.aspx
Have a look at using BinaryReader Class
Reads primitive data types as binary values in a specific encoding.
and maybe BinaryReader.ReadBytes Method
Reads the specified number of bytes from the current stream into a
byte array and advances the current position by that number of bytes.
also BinaryWriter Class
Writes primitive types in binary to a stream and supports writing
strings in a specific encoding.
Another good example C# - Copying Binary Files
for instance, one char at a time.
using (BinaryReader writer = new BinaryWrite(File.OpenWrite("target"))
{
using (BinaryReader reader = new BinaryReader(File.OpenRead("source"))
{
var nextChar = reader.Read();
while (nextChar != -1)
{
writer.Write(Convert.ToChar(nextChar));
nextChar = reader.Read();
}
}
}
The application I'm attempting to create would read the binary code of any file and create a file with the exact same binary code, creating a copy.
Is this for academic purposes? Or do you actually just want to copy a file?
If the latter, you'll want to just use the System.IO.File.Copy method.