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.
Related
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/
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.
I'm trying to create a class to manage the opening of a certain file. I would one of the properties to be a byte array of the file, but I don't know how big the file is going to be. I tried declaring the byte array as :
public byte[] file;
...but it won't allow me to set it the ways I've tried. br is my BinaryReader:
file = br.ReadBytes(br.BaseStream.Length);
br.Read(file,0,br.BaseStream.Length);
Neither way works. I assume it's because I have not initialized my byte array, but I don't want to give it a size if I don't know the size. Any ideas?
edit: Alright, I think it's because the Binary Reader's BaseStream length is a long, but its readers take int32 counts. If I cast the 64s into 32s, is it possible I will lose bytes in larger files?
I had no problems reading a file stream:
byte[] file;
var br = new BinaryReader(new FileStream("c:\\Intel\\index.html", FileMode.Open));
file = br.ReadBytes((int)br.BaseStream.Length);
Your code doesn't compile because the Length property of BaseStream is of type long but you are trying to use it as an int. Implicit casting which might lead to data loss is not allowed so you have to cast it to int explicitly.
Update
Just bear in mind that the code above aims to highlight your original problem and should not be used as it is. Ideally, you would use a buffer to read the stream in chunks. Have a look at this question and the solution suggested by Jon Skeet
You can't create unknown sized array.
byte []file=new byte[br.BaseStream.Length];
PS: You should have to repeatedly read chunks of bytes for larger files.
BinaryReader.ReadBytes returns a byte[]. There is no need to initialize a byte array because that method already does so internally and returns the complete array to you.
If you're looking to read all the bytes from a file, there's a handy method in the File class:
http://msdn.microsoft.com/en-us/library/system.io.file.readallbytes.aspx
what's the best way to write the binary representation of an int array (Int32[]) to a Stream?
Stream.Write only accepts byte[] as source and I would like to avoid converting/copying the array to an byte[] (array but instead streaming directly from the 'original location').
In a more system-oriented language (a.k.a. C++) I would simply cast the int array to a byte* but as far as I understood this isn't possible with C# (and moreover, casting byte* to byte[] wouldn't work out either way)
Thanks
Martin
PS: Actually, I would also like to stream single int values. Does using BinaryConverter.GetBytes() create a new byte array? In this case I extend my question to how to efficiently stream single int values ...
The simplest option would be to use BinaryWriter wrapping your output stream, and call Write(int) for each of your int values. If that doesn't use the right endianness for you, you could use EndianBinaryWriter from my MiscUtil library.
I don't know of anything built-in to do this more efficiently... I'd hope that the buffering within the stream would take care of it for the most part.
System.Array and System.Int32 both have the SerializableAttribute and so both support default serialization in a retrievable format.
http://msdn.microsoft.com/en-us/library/system.serializableattribute.aspx
There is sample code for Binary output and readback here:
http://msdn.microsoft.com/en-us/library/aa904194(VS.71).aspx
Im trying to write a single byte at a certain location in a file. This is what im using at the moment:
BinaryWriter bw = new BinaryWriter(File.Open(filename, FileMode.Open));
bw.BaseStream.Seek(0x6354C, SeekOrigin.Begin);
bw.Write(0xB0);
bw.Close();
The problem is that BinaryWriter.Write(args) writes a four-byte signed integer at the position. I wish to only write one byte at the particular location. And then later possibly two bytes else where, how I specify how many bytes to write?
change
bw.Write(0xB0);
to
bw.Write((byte)0xB0);
There is absolutely no need to use a high-level BinaryWriter just to write a simple byte to a stream - It's more efficient and tidy just to do this:
Stream outStream = File.Open(filename, FileMode.Open);
outStream.Seek(0x6354C, SeekOrigin.Begin);
outStream.WriteByte(0xb0);
(In general you also shouldn't really Seek after attaching a BinaryWriter to your stream - the BinaryWriter should be in control of the stream, and changing things "behind its back" is a bit dirty)
You could cast to byte:
bw.Write((byte)0xB0);
This should cause the correct overloaded version of Write to be invoked.