C# - Converting from bits to Int32 generates wrong value - c#

I am trying to convert an array of int values (each value representing a bit) to its representation as an Int32 object.
I have the following code:
//0000_0000_0000_0000_0000_0000_0000_1111 = 15
int[] numberData = new int[]
{
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 1, 1, 1, 1
};
//We convert our int[] to a bool[]
bool[] numberBits = numberData.Select(s => { return s == 0 ? false : true; }).ToArray();
//We generate a bit array from our bool[]
BitArray bits = new BitArray(numberBits);
//We copy all our bits to a byte[]
byte[] numberBytes = new byte[sizeof(int)];
bits.CopyTo(numberBytes, 0);
//We convert our byte[] to an int
int number = BitConverter.ToInt32(numberBytes, 0);
However, after executing this code, the value of number is -268435456.
Why does this happen?

The bit order is incorrect. -268435456 as a 32-bit integer is 11110000 00000000 00000000 00000000, which, as you can see, is exactly opposite what you wanted.
Just reverse your numberBits array before converting it to an Int32.
Alternatively, you could make numberData have the correct order and then never do any reversing.
Your code is working exactly how you wrote it. In numberData[0] is 0, numberData[1] is 0, ..., and numberData[31] is 1. This will cause bit 0 of your result to be 0, bit 1 to be 0, ..., and bit 31 to be 1.

Related

Save a matrix of zero and one as a sequence of bits

I have a binary matrix 8x8 represented as an one-dimensional array
byte[] m = { 0, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1,
0, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 0, 0, 0, 1,
0, 1, 1, 0, 1, 0, 0, 1,
0, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1 };
Is there a way how to save it in to binary file which would have total size of 8 bytes? Each 0 and 1 zero would be a 1 bit size.
You can use the following function to compress an array of 0s and 1s to an array of bytes:
IEnumerable<byte> Compress(byte[] a)
{
for (var i = 0; i < a.Length / 8f; i++)
{
var slice = a.Skip(i * 8).Take(8);
byte b = 0;
foreach (var s in slice)
{
b <<= 1;
if (s == 1)
b |= 1;
}
yield return b;
}
}
Then save to file using File.WriteAllBytes.
For example:
var result = Compress(m).ToArray();
File.WriteAllBytes(#"d:\test.bin", result);

Regex - How can I get different string in the same line from a log file?

I'm looking for some assistance to get specific strings from text file.
The text file has specifics words that I'm using for get the result that I'm looking for.
Here's the log example:
TLWin Session Data Log - TaskLink Version 7.90 Date Logged:
09-29-2014 02:17:45 PM Task Name: XXXXXX_A06_U1 User ID:
Administrator Mode System: PP/PS Series FlashCORE Machine ID:
123456789 Device: WINBOND_ELECTRONICS W25Q64FV-SS-Q SO8 Data
Source: c:\xptox_projects\xxxxx\xxxxxxxx(8mb).bin Sumcheck:
12345678 Process: Continuity/Blank Check/ID
Check/Erase/Program/Verify/Mark/Vision Process Status: Job Begin
Status: New Job, Job End Status: Stopped TLWin Session ID: < none >
Job Start Time: 09-29-2014 10:23:37 AM Job End Time: 09-29-2014
02:17:45 PM Devices Total: 1105 Devices Passed: 1104 Devices
Failed: 1 Overall Device Yield: 99.91% Task Description:
W25Q64FVS Nominal Throughput: 666 dph Job Throughput: 290 dph
Devices Picked Input: 1110 Devices Failed Vision: 0 Devices Failed
REST: 0 Devices Missing/In Use: 5 Job Elapsed Time: 3 Hours 0
Minutes 54 Seconds Job Setup Time: 0 Hours 0 Minutes 5 Seconds Job
Processing Time: 1 Hours 0 Minutes 40 Seconds Job Assistance Time: 2
Hours 0 Minutes 8 Seconds Job Shutdown Time: 0 Hours 0 Minutes 0
Seconds Algorithm: 3605410C.ELF Algorithm Status: Beta Algorithm
Author: Data I/O Alg COM Dll: < not used > Alg COM Dll Version: <
not used > TaskLink Version: 7.90 AH500 Version: 6.5.0 Firmware
Version: 05.52.00.C Serialization Program: < not used >
Serialization Prog Ver: < not used > Input Media: Tape Output
Media: Tape Reject 1: Tray 1 Reject 2: n/a Starting Serial
Number: N.A. Ending Serial Number: N.A. Unused Serial Numbers: N.A.
Category: PASS, CF, NB, IB, PF,VF1,VF2,FT1,FT2,SFF,SFB, DO, EF,EID, OE
TotalStats: 1104, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0,
0 Site 1 Skt 1: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0 Site 1 Skt 2: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0 Site 1 Skt 3: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0 Site 1 Skt 4: 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0 Site 2 Skt 1: 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 Site 2 Skt 2: 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0 Site 2 Skt 3: 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0 Site 2 Skt 4: 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0 Site 3 Skt 1: 139, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0 Site 3 Skt 2: 139, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 Site 3 Skt 3: 138, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 Site 3 Skt 4: 135, 1,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 Site 4 Skt 1: 141,
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 Site 4 Skt 2:
138, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 Site 4
Skt 3: 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
Site 4 Skt 4: 137, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0
Here's the specify data that I need to collect and store in somewhere:
Date Logged: 09-29-2014
Task Name: XXXXXX_A06_U1
Machine ID: 123456789
Device: WINBOND_ELECTRONICS W25Q64FV-SS-Q SO8
Devices Total: 1105
Devices Passed: 1104
Devices Failed: 1
Overall Device Yield: 99.91%
Nominal Throughput: 666
Job Throughput: 290
Devices Picked Input: 1110
Devices Failed Vision: 0
Devices Failed REST: 0
The results that I wanna to store are after the ":". The results will be send to DB through SQL procedure (next step).
Here's the code:
foreach (string file in Directory.EnumerateFiles(ConfigurationManager.AppSettings["Path"], "*.log"))
{
Regex found = new Regex(#"Date\sLogged\s*:\s*([\d\-]+).*\nTask\sName\s*:\s*(.+)[\n]|.*Machine\sID\s*:\s*(\d+)[\n]|.*Device\s*:\s*(.+)");
string fileText = File.ReadAllText(file);
string fileTextReplacement = Regex.Replace(fileText, #"\t|\n|\r"," ");
if (!string.IsNullOrEmpty(fileText))
{
if (found.Match(fileText).Success)
{
DateTime dtLogged = Convert.ToDateTime(found.Match(fileText).Groups[1].Value);
string taskName = found.Match(fileText).Groups[2].Value;
string machineId = found.Match(fileText).Groups[3].Value;
string icDevice = found.Match(fileText).Groups[4].Value;
int deviceTotal = Convert.ToInt32(found.Match(fileText).Groups[5].Value);
int devicePassed = Convert.ToInt32(found.Match(fileText).Groups[6].Value);
}
}
Any help will be very appreciated!
Thanks.
The pattern you need is essentially
(<start>)(.*)(?=<finish>)|(<start>)(.*)(?=<finish>) ... ect...
It can be simply read as
(Date Logged:) Start at "Date Logged:"
(.*) match everything in between
(?=Task Name:) End at "Task Name:"
So the next step is to just build up the pattern
// these need to be in order as seen in the log file
var tags = new List<string>()
{
"Date Logged:",
"Task Name:",
"User ID:",
"System:",
"Machine ID:",
"Device:",
"Data Source"
};
var sb = new StringBuilder();
// Create a pattern
for (var index = 1; index < tags.Count; index++)
{
// all this is doing building up your matching patern
// as described above
sb.Append($"({tags[index - 1]})(.*)(?={tags[index]})");
// dont put the OR on the end
if (index < tags.Count - 1) sb.Append("|");
}
// some input
var input = #"TLWin Session Data Log - TaskLink Version 7.90 Date Logged: 09-29-2014 02:17:45 PM Task Name: XXXXXX_A06_U1 User ID: Administrator Mode System: PP/PS Series FlashCORE Machine ID: 123456789 Device: WINBOND_ELECTRONICS W25Q64FV-SS-Q SO8 Data Source: c:\xptox_projects\xxxxx\xxxxxxxx(8mb).bin Sumcheck: 12345678 Process: Continuity/Blank Check/ID Check/Erase/Program/Verify/Mark/Vision Process Status: Job Begin Status: New Job, Job End Status: Stopped TLWin Session ID: < none >
Job Start Time: 09-29-2014 10:23:37 AM Job End Time: 09-29-2014 02:17:45 PM Devices Total: 1105 Devices Passed: 1104 Devices Failed: 1 Overall Device Yield: 99.91% Task Description: W25Q64FVS Nominal Throughput: 666 dph Job Throughput: 290 dph Devices Picked Input: ";
// do some matching
var matches = Regex.Matches(input, sb.ToString());
foreach (var match in matches)
{
Console.WriteLine(match);
}
You can see the demo here
The only caveat is it expects all the log descriptors (and in order). If this isn't the case, then you will have to modify this to search every for ever start, and every possible end and put it in a loop. which shouldn't be too difficult
(Date Logged:)(.*?)(?=(Task Name:|User ID:|System:|ect...))

c# Remove specific bytes

this might sound unclear but i know its difficult but we can remove specific bytes from byte[] array but if the array contain similiar values while removing values it can remove other values i m using :
byte[] B = new byte[] { 10, 0, 0, 10 };
byte[] D = new byte[] { 0, 0 };
byte[] NewArray = B.Except(D).ToArray();
BytesDisplayer.Text = String.Join(",", NewArray);
but lets say i have a byte as:
byte[] Data = new byte[] {0,10,10,10,0,5,5,5,10,10,10};
and i want to remove the last 3 values (10) My method will remove all the 10 value on that array , so basically i want to know is there is a way to remove specific bytes in specific indexes and how ?
try this:
byte[] Data = new byte[] { 0, 10, 10, 10, 0, 5, 5, 5, 10, 10, 10 };
Data = Data.Where((item, index) => index < 8).ToArray();

How to compare OracleTimeStamps

I have two byte[] (like this { 0, 0, 0, 0, 52, 246, 141, 6 }) that represent two Oracle's timestamps.
How do I know which one is older?
Convert the binary timestamp to Int64 and then compare the corresponding long values:
var value = new byte[] { 0, 0, 0, 0, 52, 246, 141, 6 };
long timestamp = BitConverter.ToInt64(value, 0);
The bigger the long value, the more recent the timestamp. I haven't used Oracle but I would guess this represents the number of ticks since the Epoch.

Collection was modified; enumeration operation may not execute." Collection elements are not modified

I have a nested loop "structure" in my code. Sometimes, I get the below message.
Collection was modified; enumeration operation may not execute.
I have a collection I am looping through, like below. Coll is a List<string>
foreach (string[] s1 in obj.Coll
{
foreach (string s in s1) { }
}
For each string in the array, I need to work with it (read as read the value, not write).
All I do with it is get directories (this value is a path) and split this string into an array.
How can this be resolved?
The obj.Coll is changed while you are enumerating it. If it is not changed by the current thread, it may be changed by some other thread. If the collection is changed by the current thread, there are basically two ways to solve the problem: You can create a copy of the collection and enumerate the copy or you can postpone the changes until you have enumerated the collection.
However, if the collection is changed by another thread, you should access the collection in a thread-safe manner (not just here but everywhere).
EDIT for Kieren Johnstone:
I wrote a short code to demonstrate that List<T>.ToArray() is not thread-safe.
var list = new List<int>();
Task.Factory.StartNew(() => {
for (int i = 0; i < 1000000; ++i) {
list.Clear();
// Add values from 1 to 9
for (int j = 1; j < 10; ++j) {
list.Add(j);
}
}
Console.WriteLine("Thread Exit: list.Add()");
});
Task.Factory.StartNew(() => {
for (int i = 0; i < 100; ++i) {
var array = list.ToArray();
if (array.Length > 0) {
Console.WriteLine("ToArray(): {0}", string.Join(", ", array));
}
}
Console.WriteLine("Thread Exit: list.ToArray()");
});
And below is a snippet of the output. I guess that it proves my claim. The snippet contains 15 lines and nine of them contain bad data.
ToArray(): 1, 2, 3, 4
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4, 5, 6, 7, 0, 0
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4, 5, 0, 0, 0, 0
ToArray(): 0, 0, 0, 4, 5, 6, 7
ToArray(): 1, 2, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3
ToArray(): 1, 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2
ToArray(): 1, 2, 3
ToArray(): 0, 0, 0, 0, 0, 0, 0, 0
ToArray(): 1, 2, 3, 4
ToArray(): 1, 2, 3, 4, 5, 6, 7, 8
There would be more variations if we had used list.Insert(0, j) instead of list.Add(j).
You can try:
foreach (string[] s1 in obj.Coll.ToArray())
{
That will take a copy before starting iteration!

Categories

Resources