Friday, January 14, 2011

C# code to parse an x9.37 file

The following C# code will parse an X937 file (Image Cash Letter) and get the amounts of each check

// BigEndianBitConverter class taken from http://www.yoda.arachsys.com/csharp/miscutil/

        // ConvertEBCDICtoASCII method taken from http://kseesharp.blogspot.com/2007/12/convert-ebcdic-to-ascii.html

        static void Main(string[] args)

        {

            var input = new BinaryReader(new FileStream("YourICLFile.icl",FileMode.Open));

            byte[] amount_bytes, record_type_bytes;

            byte[] record_lenght_bytes = input.ReadBytes(4);

            var converter = new BigEndianBitConverter();

            int record_lenght = converter.ToInt32(record_lenght_bytes,0);

            string record_type, amount_str;

 

            //Totals

            long check_items= 0, total_amount = 0;

            try

            {

 

                while (true)

                {

                    //Get record type

                    record_type_bytes = input.ReadBytes(2);

                    record_type = ConvertEBCDICtoASCII(record_type_bytes);

                    if (record_type == "99") //file control (end of file)

                        break;

 

                    if (record_type == "25") //check detail

                    {

                        check_items++;

                        input.ReadBytes(45); //move the stream's position to the field containing the amount of the check

                        amount_bytes = input.ReadBytes(10);

                        amount_str = ConvertEBCDICtoASCII(amount_bytes);

                        Console.Out.WriteLine(check_items);

                        Console.Out.WriteLine("$ " + amount_str);

                        total_amount += long.Parse(amount_str);

                        input.ReadBytes(record_lenght - (2 + 45 + 10)); //move the stream's position to the next record

                    }

                    else

                    {

                        input.ReadBytes(record_lenght - 2); //move the stream's position to the next record

                    }

                   

 

                    //Get next record's size

                    record_lenght_bytes = input.ReadBytes(4);

                    record_lenght = converter.ToInt32(record_lenght_bytes, 0);

                }

            }

            catch (EndOfStreamException end)

            {

 

            }

            finally

            {

                input.Close();

            }

 

            Console.Out.WriteLine("Number of items: " + check_items);

            Console.Out.WriteLine("$ " + ((decimal)total_amount / (decimal)100));

            Console.ReadLine();

        }

Please note that the code above is for demonstration purposes, you can optimize the reading of the file by using File.OpenRead.

2 comments:

Anonymous said...

Hi, thank you for your post. Can you tell me how you got past the fact that the ConvertEBCDICtoASCII function requires a string argument, you are passing "record_type_bytes" which is of 'byte[]' type.
Thanks again

Juan Pablo said...

Just change the strEBCDICString parameter to be byte[]. Then change the lines of the method to use the array instead of a string. E.g.: instead of Convert.ToChar(strEBCDICString.Substring(i, 1)) you should be able to do something like this: (char)strEBCDICString[i].