+14  A: 

Your code is silently catching any exception that happens in the while loop and swallowing it.

This is a bad practice because it masks issues like the one you are running into.

Most likely, one of the methods you call inside the loop (int.Parse() for example) is throwing an exception because it encounters some problem in the format of the data (or your assumptions about that format).

Once an exception occurs, the loop that reads data is thrown off kilter because it is no longer positioned at a record boundary.

You should do several things to make this code more resilient:

  1. Don't silently swallow exception in the run loop. Deal with them.
  2. Don't read data byte by byte or field by field in the loop. Since your records are fixed size (77 bytes) - read an entire record into a byte[] and then process it from there. This will help ensure you are always reading at a record boundary.
LBushkin
+1, 2 good advices.
Henk Holterman
+1, reading the record in its entirety is a good idea. You could even wrap that array in a `BinaryReader` over a `MemoryStream` and still get the convenience of the built-in conversion functions.
Adam Robinson
thanks for the advice. i implemented some changes based on what you've said and i edited the original to show the updated code. however, the problem still hasn't been fixed. when i ran it before the code changes, i once got an EndOfStreamException which i thought was weird. currently, the same problem exists but there are no errors thrown at all. any thoughts?
Slim
Things to check: 1) is your test file corrupt? Try a different file if you have one. 2) are some records a different size than 77 bytes? Manually examine the data in the region of the file you're dealing with, 3) is there a logic error in the code? try skipping the first 15.5 million records (don't process them just fast forward the stream) and single-step in the debugger to see what's happening
LBushkin
to answer your questions: 1) it is not a corrupt file. i will generate another one for testing, though that takes approx 12 hrs. 2) all records up to and after this break are 77 bytes in length... 3) i skipped ahead and discovered that a few million bytes after it breaks, i find a packet length 78 bytes which throws things off later (however unrelated to initial "breaking" problem).. which means my problem is 2-fold (see next comment - apologies if double commenting is against site policies): my reader and writer both break after a certain length (variable, around 100 million bytes)
Slim
i thought my reader was fixed here: http://stackoverflow.com/questions/1595325/serialport-data-loss-c after implementing hardware handshaking. it seems not. i'm still using what's presented in the 2nd chunk of code. my code handles incorrect packet lengths by filling in all "0"s instead of actual data (not shown). however, the reader still breaks (cuts off in the middle of a packet) after a certain length regardless of where in the stream i begin processing (this time after 24.5 million lines of output). note there are 32 lines of output per packet if that's relevant.
Slim
update (sorry for triple post now!): it seems this "breaking" issue may be due to my text editors not being able to open files of these sizes. opening the same file with a different amount of memory usage in the system as a whole produces text files of varying lengths. i may be interpreting the text editor's memory handling as a fault in my code. i'm working on testing this somehow, possibly with new text editors in combination with breakpoints
Slim
+2  A: 
  • Don't put an empty generic catch block here and just silently catch and continue. You should check and see if you're getting an actual exception in there and go from there.
  • There is no need for the byteToHexString function. Just use the 0x prefix before a hexadecimal number and it will do a binary comparison.

i.e.

if(al[0] == 0x16 && al[1] == 0x3C && al[2] == 0x02)
{
    ...
}
  • I don't know what your doConvert function does (you didn't provide that source), but the BinaryReader class provides many different functions, one of which is ReadInt16. Unless your shorts are stored in an encoded format, that should be easier to use than doing your fairly obfuscated and confusing conversion. Even if they're encoded, it would still be far simpler to read the bytes in and manipulate them, rather than doing several roundtrips with converting to strings.

Edit

You appear to be making very liberal use of the LINQ extension methods (particularly ElementAt). Every time you call that function, it enumerates your list until it reaches that number. You'll have much better performing code (as well as less verbose) if you just use the built-in indexer on the list.

i.e. al[3] rather than al.ElementAt(3).

Also, you don't need to call Flush on an input Stream. Flush is used to tell the stream to write anything that it has in its write buffer to the underlying OS file handle. For an input stream it won't do anything.

I would suggest replacing your current sw.WriteLine call with this:

sw.WriteLine(BitConverter.ToString(packet)); and see if the data you're expecting on the row where it starts to mess up is actually what you're getting.

I would actually do this:

if (packet.Take(3).SequenceEqual(STARTCODE) &&
    packet.Skip(packet.Length - ENDCODE.Length).SequenceEqual(ENDCODE))
{
    ushort id = BitConverter.ToUInt16(packet, 3);
    ushort semistable = BitConverter.ToUInt16(packet, 5);
    byte contant = packet[7];

    for(int i = 8; i < 72; i += 2)
    {
        il.Add(BitConverter.ToUInt16(packet, i));
    }

    foreach(ushort element in il)
    {
        sw.WriteLine(string.Format("{0},{1},{2},{3}", id, semistable, constant, element);
    }

    il.Clear();
}
else
{
    //handle "bad" packets
}
Adam Robinson
ahh that makes things much easier. thanks for the heads up. the original code has been edited to reflect the updates, but the original problem still remains :\
Slim
thanks much for the good advice. i am very new to c# and appreciate the info - much easier, both on mem usage and my code. in addition, your suggestion write out the entire packet.ToString() led to the discovery of my possible text editor memory handling problem (see comments above to LBushkin's reply). *hopefully* (pending investigation) now my only issue is that either my binary writer is having an issue or the device sent an invalid packet
Slim