I need to reproduce in C# a MATLAB code I found, which reads a binary file. The code is:
% Skip header
fread(fid, 1, 'int32=>double', 0, 'b');
% Read one property at the time
i = 0;
while ~feof(fid)
i = i + 1;
% Read field name (keyword) and array size
keyword = deblank(fread(fid, 8, 'uint8=>char')');
keyword = strrep(keyword, '+', '_');
num = fread(fid, 1, 'int32=>double', 0, 'b');
% Read and interpret data type
dtype = fread(fid, 4, 'uint8=>char')';
End
fclose(fid)
I’ve tried several methods of reading binary files in C#, but I haven’t got the right results. How should I proceed?
this is what i've done, that seems to kind of work so far
FileStream fs = new FileStream(filename, FileMode.Open);
BinaryReader binreader = new BinaryReader(fs,Encoding.Default);
//skip head
binreader.ReadInt32();
for (int i = 0; i < 8; i++)
{
keyword = keyword + binreader.ReadChar();
}
keyword = keyword.TrimEnd();
keyword = keyword.Replace("+", "_");
num = binreader.ReadInt32();
for (int i = 0; i < 4; i++)
{
dtype = dtype + binreader.ReadChar();
}
the problem is that i should obtein: keyword=INTERHEAD, num=411 and dtype=INTE
but what Im getting is: keyword=INTERHEAD, num=-1694433280 and dtype=INTE
the problem is in getting the num variable right.
I've changed readint32 to readdouble, readUint32 and so on but never got 411.
Any help?
Related
I have 2 files.
1 is Source File and 2nd is Destination file.
Below is my code for Intersect and Union two file using byte array.
FileStream frsrc = new FileStream("Src.bin", FileMode.Open);
FileStream frdes = new FileStream("Des.bin", FileMode.Open);
int length = 24; // get file length
byte[] src = new byte[length];
byte[] des = new byte[length]; // create buffer
int Counter = 0; // actual number of bytes read
int subcount = 0;
while (frsrc.Read(src, 0, length) > 0)
{
try
{
Counter = 0;
frdes.Position = subcount * length;
while (frdes.Read(des, 0, length) > 0)
{
var data = src.Intersect(des);
var data1 = src.Union(des);
Counter++;
}
subcount++;
Console.WriteLine(subcount.ToString());
}
}
catch (Exception ex)
{
}
}
It is works fine with fastest speed.
but Now the problem is that I want count of it and when I Use below code then it becomes very slow.
var data = src.Intersect(des).Count();
var data1 = src.Union(des).Count();
So, Is there any solution for that ?
If yes,then please lete me know as soon as possible.
Thanks
Intersect and Union are not the fastest operations. The reason you see it being fast is that you never actually enumerate the results!
Both return an enumerable, not the actual results of the operation. You're supposed to go through that and enumerate the enumerable, otherwise nothing happens - this is called "deferred execution". Now, when you do Count, you actually enumerate the enumerable, and incur the full cost of the Intersect and Union - believe me, the Count itself is relatively trivial (though still an O(n) operation!).
You'll need to make your own methods, most likely. You want to avoid the enumerable overhead, and more importantly, you'll probably want a lookup table.
A few points: the comment // get file length is misleading as it is the buffer size. Counter is not the number of bytes read, it is the number of blocks read. data and data1 will end up with the result of the last block read, ignoring any data before them. That is assuming that nothing goes wrong in the while loop - you need to remove the try structure to see if there are any errors.
What you can do is count the number of occurences of each byte in each file, then if the count of a byte in any file is greater than one then it is is a member of the intersection of the files, and if the count of a byte in all the files is greater than one then it is a member of the union of the files.
It is just as easy to write the code for more than two files as it is for two files, whereas LINQ is easy for two but a little bit more fiddly for more than two. (I put in a comparison with using LINQ in a naïve fashion for only two files at the end.)
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var file1 = #"C:\Program Files (x86)\Electronic Arts\Crysis 3\Bin32\Crysis3.exe"; // 26MB
var file2 = #"C:\Program Files (x86)\Electronic Arts\Crysis 3\Bin32\d3dcompiler_46.dll"; // 3MB
List<string> files = new List<string> { file1, file2 };
var sw = System.Diagnostics.Stopwatch.StartNew();
// Prepare array of counters for the bytes
var nFiles = files.Count;
int[][] count = new int[nFiles][];
for (int i = 0; i < nFiles; i++)
{
count[i] = new int[256];
}
// Get the counts of bytes in each file
int bufLen = 32768;
byte[] buffer = new byte[bufLen];
int bytesRead;
for (int fileNum = 0; fileNum < nFiles; fileNum++)
{
using (var sr = new FileStream(files[fileNum], FileMode.Open, FileAccess.Read))
{
bytesRead = bufLen;
while (bytesRead > 0)
{
bytesRead = sr.Read(buffer, 0, bufLen);
for (int i = 0; i < bytesRead; i++)
{
count[fileNum][buffer[i]]++;
}
}
}
}
// Find which bytes are in any of the files or in all the files
var inAny = new List<byte>(); // union
var inAll = new List<byte>(); // intersect
for (int i = 0; i < 256; i++)
{
Boolean all = true;
for (int fileNum = 0; fileNum < nFiles; fileNum++)
{
if (count[fileNum][i] > 0)
{
if (!inAny.Contains((byte)i)) // avoid adding same value more than once
{
inAny.Add((byte)i);
}
}
else
{
all = false;
}
};
if (all)
{
inAll.Add((byte)i);
};
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
// Display the results
Console.WriteLine("Union: " + string.Join(",", inAny.Select(x => x.ToString("X2"))));
Console.WriteLine();
Console.WriteLine("Intersect: " + string.Join(",", inAll.Select(x => x.ToString("X2"))));
Console.WriteLine();
// Compare to using LINQ.
// N/B. Will need adjustments for more than two files.
var srcBytes1 = File.ReadAllBytes(file1);
var srcBytes2 = File.ReadAllBytes(file2);
sw.Restart();
var intersect = srcBytes1.Intersect(srcBytes2).ToArray().OrderBy(x => x);
var union = srcBytes1.Union(srcBytes2).ToArray().OrderBy(x => x);
Console.WriteLine(sw.ElapsedMilliseconds);
Console.WriteLine("Union: " + String.Join(",", union.Select(x => x.ToString("X2"))));
Console.WriteLine();
Console.WriteLine("Intersect: " + String.Join(",", intersect.Select(x => x.ToString("X2"))));
Console.ReadLine();
}
}
}
The counting-the-byte-occurences method is roughly five times faster than the LINQ method on my computer, even without the latter loading the files and on a range of file sizes (a few KB to a few MB).
I have no idea where to ask a question like this, so probably should say sorry right away.
Private Function RCON_Command(ByVal Command As String, ByVal ServerData As Integer) As Byte()
Dim Packet As Byte() = New Byte(CByte((13 + Command.Length))) {}
Packet(0) = Command.Length + 9 'Packet Size (Integer)
Packet(4) = 0 'Request Id (Integer)
Packet(8) = ServerData 'SERVERDATA_EXECCOMMAND / SERVERDATA_AUTH (Integer)
For X As Integer = 0 To Command.Length - 1
Packet(12 + X) = System.Text.Encoding.Default.GetBytes(Command(X))(0)
Next
Return Packet
End Function
Can someone tell me how should this code look like in c#? Tried my self but always getting error Cannot implicitly convert type 'int' to 'byte'. An explicit conversion exists (are you missing a cast?)
Tried to cast, then getting error about no need to cast
My code:
private byte[] RCON_Command(string command, int serverdata)
{
byte[] packet = new byte[command.Length + 13];
packet[0] = command.Length + 9;
packet[4] = 0;
packet[8] = serverdata;
for (int i = 0; i < command.Length; i++)
{
packet[12 + i] = System.Text.Encoding.UTF8.GetBytes(command[i])[0];
}
return packet;
}
error is in packet[0] and packet [8] line
You need to cast the two items to byte before assigning them. Another option I've done below is to change the method to accept serverdata as a byte instead of int - there's no point in taking the extra bytes only to throw them away.
Another problem is in the for loop - the indexer of string returns a char, which UTF8.GetBytes() can't accept. I think my translation should work, but you'll need to test it.
private byte[] RCON_Command(string command, byte serverdata)
{
byte[] packet = new byte[command.Length + 13];
packet[0] = (byte)(command.Length + 9);
packet[4] = 0;
packet[8] = serverdata;
for (int i = 0; i < command.Length; i++)
{
packet[12 + i] = System.Text.Encoding.UTF8.GetBytes(command)[i];
}
return packet;
}
Here you go. The Terik converter was no use - that code wouldn't compile.
This code runs...
private byte[] RCON_Command(string Command, int ServerData)
{
byte[] commandBytes = System.Text.Encoding.Default.GetBytes(Command);
byte[] Packet = new byte[13 + commandBytes.Length + 1];
for (int i = 0; i < Packet.Length; i++)
{
Packet[i] = (byte)0;
}
int index = 0;
//Packet Size (Integer)
byte[] bytes = BitConverter.GetBytes(Command.Length + 9);
foreach (var byt in bytes)
{
Packet[index++] = byt;
}
//Request Id (Integer)
bytes = BitConverter.GetBytes((int)0);
foreach (var byt in bytes)
{
Packet[index++] = byt;
}
//SERVERDATA_EXECCOMMAND / SERVERDATA_AUTH (Integer)
bytes = BitConverter.GetBytes(ServerData);
foreach (var byt in bytes)
{
Packet[index++] = byt;
}
foreach (var byt in commandBytes)
{
Packet[index++] = byt;
}
return Packet;
}
In addition to the need for casting, you need to be aware that C# uses array sizes when creating the array, not the upper bound that VB uses - so you need "14 + Command.Length":
private byte[] RCON_Command(string Command, int ServerData)
{
byte[] Packet = new byte[Convert.ToByte(14 + Command.Length];
Packet[0] = Convert.ToByte(Command.Length + 9); //Packet Size (Integer)
Packet[4] = 0; //Request Id (Integer)
Packet[8] = Convert.ToByte(ServerData); //SERVERDATA_EXECCOMMAND / SERVERDATA_AUTH (Integer)
for (int X = 0; X < Command.Length; X++)
{
Packet[12 + X] = System.Text.Encoding.Default.GetBytes(Command[X])[0];
}
return Packet;
}
Just add the explicit casts. You might want to make sure that it's safe to down cast from a 32-bit value type to an 8-bit type.
packet[0] = (byte)(command.Length + 9);
...
packet[8] = (byte)serverdata;
EDIT:
TheEvilPenguin is also right that you will have a problem with your call to GetBytes().
This is how I would fix it to make sure I don't change the meaning of the existing VB.NET code:
packet[12 + i] = System.Text.Encoding.UTF8.GetBytes(new char[] {command[i]})[0];
And also, one more detail:
When you declare an array in VB.NET, you define the maximum array index. In C#, the number in the array declaration represents the number of elements in the array. This means that in the translation from VB.NET to C#, to keep equivalent behavior, you need to add + 1 to the number in the array declaration:
byte[] packet = new byte[command.Length + 13 + 1]; // or + 14 if you want
I am trying to take a PDF document and upload it via a MVC website to be stored into an SAP structure. The SAP structure requires the byte array to be broken up into 1022 length sections. The program seems to work good up to the point where I try to view the PDF document out of SAP. Unfortunately, I cannot view the PDF data stored in SAP due to access rights. So, I created a sort of MOCK program to match up the byte array from before it is sent to SAP (fileContent) and then what it should look like once it is returned from SAP (fileContentPostSAP).
The program compares the byte arrays and finds mismatching values at array location 1022.
Is there a bug in my program that is causing the byte arrays to not match? They are supposed to match exactly, right?
ClaimsIdentityMgr claimIdentityMgr = new ClaimsIdentityMgr();
ClaimsIdentity currentClaimsIdentity = claimIdentityMgr.GetCurrentClaimsIdentity();
var subPath = "~/App_Data/" + currentClaimsIdentity.EmailAddress;
var destinationPath = Path.Combine(Server.MapPath(subPath), "LG WM3455H Spec Sheet.pdf");
byte[] fileContent = System.IO.File.ReadAllBytes(destinationPath);
//pretend this is going to SAP
var arrList = SAPServiceRequestRepository.CreateByteListForStructure(fileContent);
var mockStructureList = new List<byte[]>();
foreach (byte[] b in arrList)
mockStructureList.Add(b);
//now get it back from Mock SAP
var fileContentPostSAP = new byte[fileContent.Count()];
var rowCounter = 0;
var prevLength = 0;
foreach (var item in mockStructureList)
{
if (rowCounter == 0)
System.Buffer.BlockCopy(item, 0, fileContentPostSAP, 0, item.Length);
else
System.Buffer.BlockCopy(item, 0, fileContentPostSAP, prevLength, item.Length);
rowCounter++;
prevLength = item.Length;
}
//compare the orginal array with the new one
var areEqual = (fileContent == fileContentPostSAP);
for (var i = 0; i < fileContent.Length; i++)
{
if (fileContent[i] != fileContentPostSAP[i])
throw new Exception("i = " + i + " | fileContent[i] = " + fileContent[i] + " | fileContentPostSAP[i] = " + fileContentPostSAP[i]);
}
And here is the CreateByteListForStructure function:
public static List<byte[]> CreateByteListForStructure(byte[] fileContent)
{
var returnList = new List<byte[]>();
for (var i = 0; i < fileContent.Length; i += 1022)
{
if (fileContent.Length - i >= 1022)
{
var localByteArray = new byte[1022];
System.Buffer.BlockCopy(fileContent, i, localByteArray, 0, 1022);
returnList.Add(localByteArray);
}
else
{
var localByteArray = new byte[fileContent.Length - i];
System.Buffer.BlockCopy(fileContent, i, localByteArray, 0, fileContent.Length - i);
returnList.Add(localByteArray);
}
}
return returnList;
}
There seems to be a simple bug in the code.
This loop, which reconstructs the contents of the array from the blocks:
var prevLength = 0;
foreach (var item in mockStructureList)
{
if (rowCounter == 0)
System.Buffer.BlockCopy(item, 0, fileContentPostSAP, 0, item.Length);
else
System.Buffer.BlockCopy(item, 0, fileContentPostSAP, prevLength, item.Length);
rowCounter++;
prevLength = item.Length;
}
By the description of the blocks, every block is 1022 bytes, which means that after the first iteration, prevLength is set to 1022, but after the next iteration it is set to 1022 again.
The more correct assignment of prevLength would be this:
prevLength += item.Length;
^
|
+-- added this
This will correctly move the pointer in the output array forward one block at a time, instead of moving it to the second block and then leaving it there.
Basically you write block 0 in the correct place, but all the other blocks on top of block 1, leaving block 2 and onwards in the output array as zeroes.
everyone,
now i'm writing a C# programm according to a piece of matlab code.
In matlab code there are two commands to read data from the COM-Port:
A=fscanf(com_Port1,'%s');
A=fread(com_Port1,1008); //two sentences are next to each other like i write here.
For the first command "A=fscanf(com_Port1,'%s');" i used:
string A = com_Port1.ReadExisting();
and it seems all right, because no error warning;
for the second command "A=fread(com_Port1,1008);" i used:
double[] B = new double[1008];
for (int i = 0; i <= 1008 - 1; i++)
{
B[i] = com_Port1.ReadByte() ;
}
then it shows an error:
"A first chance exception of type 'System.TimeoutException' occurred
in System.dll".
So i'm assuming that "ReadExisting" has read all the data, and "ReadByte" can't read available data any more, is that right?Could someone tell me where i war wrong? thank you.
Yours
Adam
Add at Nov.20.2013, below is the code i have wrote, i have tried "Read()","ReadTo()","ReadLine()", but i still get the error at "otdr_Portobject.ReadByte()", i have no idea any more.
otdr_Portobject = new otdr_Port(cB_portNames.SelectedItem.ToString());
otdr_Portobject.Open();
btn_Stop.Enabled = true;
btn_Start.Enabled = false;
/*if (!otdr_Portobject.IsOpen)
{
MessageBox.Show("not open");
}
else {
MessageBox.Show("Serial Port opened");
};*/
//string start = "start";
otdr_Portobject.Write("start");
char[] b9 = new char[7];
otdr_Portobject.Read(b9, 0, 7);
Thread.Sleep(5000);
//string isready = "isready";
otdr_Portobject.Write("isready");
char[] b10 = new char[10];
otdr_Portobject.Read(b10, 0, 10);
//A = otdr_Portobject.ReadTo("\n");
//string rdatb = "rdatb";
int int32_Auslesekommando = Convert.ToInt32(pointsCon.Value-1);
otdr_Portobject.Write("rdatb " + int32_Auslesekommando.ToString("X4") + "\n");
Thread.Sleep(50);
char[] b11 = new char[18];
otdr_Portobject.Read(b11, 0, 18);
//A = otdr_Portobject.ReadTo("\n");
//A = otdr_Portobject.ReadTo("\n");
//int A1=otdr_Portobject.ReadByte();
//brechnen Y Axis
int pointNum = Convert.ToInt32(pointsCon.Value);
double[] B = new double[pointNum];
//int byteNum=otdr_Portobject.BytesToRead;
//if ( byteNum== 0) return;
try
{
for (int i = 0; i <= pointNum - 1; i++)
{
B[i] =System.Convert.ToDouble( otdr_Portobject.ReadByte() )* 256;
}
}
catch(UnauthorizedAccessException ex)
{
MessageBox.Show(ex.Message);
}
From the c#-docs:
ReadExsting: Reads all immediately available bytes, based on the encoding, in both the stream and the input buffer of the SerialPort object..
MATLAB:
%s format for fscanf: Read series of characters, until find white space.
So you should probably switch to ReadTo, specifying a white-space character to stop.
Or call Read yourself until the returned value is a whitespace-character.
I have this code wich is working when writing a binary file:
using (BinaryWriter binWriter =
new BinaryWriter(File.Open(f.fileName, FileMode.Create)))
{
for (int i = 0; i < f.histogramValueList.Count; i++)
{
binWriter.Write(f.histogramValueList[(int)i]);
}
binWriter.Close();
}
And this code to read back from the DAT file on the hard disk:
fileName = Options_DB.get_histogramFileDirectory();
if (File.Exists(fileName))
{
BinaryReader binReader =
new BinaryReader(File.Open(fileName, FileMode.Open));
try
{
//byte[] testArray = new byte[3];
int pos = 0;
int length = (int)binReader.BaseStream.Length;
binReader.BaseStream.Seek(0, SeekOrigin.Begin);
while (pos < length)
{
long[] l = new long[256];
for (int i = 0; i < 256; i++)
{
if (pos < length)
l[i] = binReader.ReadInt64();
else
break;
pos += sizeof(Int64);
}
list_of_histograms.Add(l);
}
}
catch
{
}
finally
{
binReader.Close();
}
But what i want to do is to add to the Writing code to write to the file more three streams like this:
binWriter.Write(f.histogramValueList[(int)i]);
binWriter.Write(f.histogramValueListR[(int)i]);
binWriter.Write(f.histogramValueListG[(int)i]);
binWriter.Write(f.histogramValueListB[(int)i]);
But the first thing is how can i write all this and make it in the file it self to be identify by a string or something so when im reading the file back i will be able to put each List to a new one ?
Second thing is how do i read back the file now so each List will be added to a new List ?
Now it's easy im writing one List reading and adding it to a List.
But now i added more three Lists so how can i do it ?
Thanks.
To get answer think about how to get number of items in list that you've just serialized.
Cheat code: write number of items in collection before items. When reading do reverse.
writer.Write(items.Count());
// write items.Count() items.
Reading:
int count = reader.ReadInt32();
items = new List<ItemType>();
// read count item objects and add to items collection.