February 2008 Entries

I’ve been working on a project that was supposed to be a pretty quick windows service that simply extracted some images and matched up those images in an index file. We (the company I work for) are doing this for a client of ours to aide them in their billing process.
We have an application that scans checks and payment stubs. It’s my job to create something that can extract the images from the scanned documents and supply a all the payment information associated with that check/stub. The company that we are doing this for made changes to the specifications every meeting we had. We started back in November, Now I am ready to deliver the final product. Oh yeah, we had a change today - J
There are many interesting things with this application. The first thing I had figure out was how to parse through a comma delimited file to get the image name, and the accounting/payment info. My text reader was fairly simply; I just read one line at a time, putting each comma-ed item in an array.
public static string[][] Dissasemble(string input, char[] seperator)
        {
            List<string> rows = new List<string>(input.Split('\n'));
            List<List<string>> xmlItems = new List<List<string>>(rows.Count);
            List<string[]> result = new List<string[]>(rows.Count);
 
            foreach (string str in rows)
                if (!String.IsNullOrEmpty(str))
                    xmlItems.Add(new List<string>(str.Split(seperator)));
 
            // figure out how many items we should expect on each line
            int count = xmlItems[0].Count;
 
            for (int i = 0; i < rows.Count; i++)
            {
                if (count != xmlItems[i].Count)
                    throw new ArgumentException("input is not correctly formatted -- all rows should have the same number of items");
 
                result.Add(xmlItems[i].ToArray());
            }
 
            return result.ToArray();
 
One of the items in the string array is the name of the image. Working with images was much easier than I anticipated. Some of the images needed to return the front side of the check, some needed to send both the front and the back. Luckily the application that scans and stores the images, has a web interface to extract the image.
First I have to create the uri line;
string webreq = "http://" + Properties.Settings.Default.ImageServerIPAddress + "/imgreq/imgreqis.dll?IC&Date=" + MainClass.fixdate(ItemDate, "reg") + "&Item=" + ItemID + "side=" + Side;
Once I have the line built, I read and write to the html file stream. The interesting thing I found out is the image application returns a png. But the client wants a tiff. Converting a png to a tiff as simple!
WriteBytesToFile(Properties.Settings.Default.Images + @"\" + ItemID + ".png", GetBytesFromUrl(webreq));
                    img = Image.FromFile(Properties.Settings.Default.Images + @"\" + ItemID + ".png");
                    string fullname = Properties.Settings.Default.Images + @"\tempimages" + @"\IMG" + ItemID + Side + ".tif";
                    img.Save(fullname, ImageFormat.Tiff);
                    img.Dispose();
The WriteBytesToFile method:
FileStream fs = new FileStream(fileName, FileMode.Create);
            BinaryWriter w = new BinaryWriter(fs);
            try
            {
                w.Write(content);
            }
            finally
            {
                fs.Close();
                w.Close();
            }
 
The next thing the client wanted was all the images in a zip file. Unless you use one of the paid or free zip classes, C# and zip is difficult but not impossible. To create an empty zip file;
byte[] emptyzip = new byte[] { 80, 75, 5, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
 
                FileStream fs1 = File.Create(Properties.Settings.Default.FileSaveLocation + @"\" + zipname());
                fs1.Write(emptyzip, 0, emptyzip.Length);
                fs1.Flush();
                fs1.Close();
                fs1 = null;
 
To copy the images to the zip file I had to use shell commands;
Shell32.ShellClass sc = new Shell32.ShellClass();
                Shell32.Folder SrcFlder = sc.NameSpace(Properties.Settings.Default.Images + @"\tempimages");
                Shell32.FolderItems fi = SrcFlder.Items(); //..Item(OriginalFileName);
                Shell32.Folder DestFlder = sc.NameSpace(Properties.Settings.Default.FileSaveLocation + @"\" + ZipClass.zipname());
                DestFlder.CopyHere(fi, 1024);
               
                Thread.Sleep(SrcFlder.Items().Count * 1000);
 
Of course there are other parts, for example I had to supply separate text files in particular formats for the client – boring stuff. Up until today, I was under the impression I could simply copy the files to a folder for the client extract through their FTP connection. Today I found out our FTP server cannot be reached through a file share. Thus I had to learn a thing or two about programming a FTP client.
FTP is .net sockets, user names, passwords and all the regular IO commands. But everything is done via a stream. This was a pretty big class. I had to both write to the stream and read from the stream. Some of the highlights are;
Sending commands
if (Responses)
                        log.WriteLine("---> " + command);
                 
                  // send it
                  writer.Write(command + "\r\n");
                  writer.Flush();
                 
                  // and read the result
                  return Reply();
 
Uploading files:
if (TransferType == FTPTransferType.ASCII)
                  {
                        Stream srcStream =
                        new FileStream(localPath, FileMode.Open, FileAccess.Read);
                 
                  }
                  else
                  {
                        Stream srcStream =
                        new FileStream(localPath, FileMode.Open, FileAccess.Read);
                  PutBinary(srcStream, remoteFile, append);            
}
 
                  Validate();
 
Tomorrow, I’m hoping to have some real data to test with. If all goes well, I can release this week!
 
 
Another great meeting!!! Tonight I walked in with Bill; I got to help push the mounds of food and drinks in. As usual the meeting was held at the Microsoft Malvern campus. The meeting started with Dani Diaz our local MS rep. His course was named VS c# Tips and Tricks for the MS Visual Studio 2008 IDE.
Dani started out with showing us around VS 2008, key commands, explaining the versioning and how it works, etc. Some of the key commands that he showed were pretty cool, ones I never saw before. Then he went into some of the code changes, things like how we no longer need to add local variables to properties and not having to type new for objects where you are adding the properties when instantiate the values. Name Object initializers (also collection initializers).  He obviously talked about LINQ, and how to write code using it.
Tonight Devon Consulting sponsored the event. They supplied all the food – lots of food – 90 people or so!!! One of the leaders of Devon spoke about how they get jobs… And they gave away a GPS unit.
Our main speaker of the night was David Solivan, another MS evangelist. His subject was the magic of Application Life Cycle. He started off speaking about how many projects fail and how many succeed. How we manage requirement changes and quality. The problem is it takes more than developers to produce a solution. The new focus is People, process, tools. (The Team System).  
We had a discussion on Team Foundation Server and the advances MS made compared to Source Safe. Dave showed how much better the team editions are over the ole individual versions. He showed how much more useful the Team Editions are. Showed the entire life cycle of a development project and how each person’s role is just as important as the others. Microsoft is shifting from selling to just developers. They realize there is an entire team of people that are required to properly get a development project completed.
The night as most of the meetings was a 10! Meaning GREAT!
If you are not in a user group you are missing out!