Tuesday, December 15, 2009

Keep Your Head Up

{

From an old Raganwald interview, I derived some inspiration this morning:

“Quite often we see something and we're very tempted to say "oh! this is a special case of a more general thing." and then we solve the general thing. However that is an infinite recursion: it's always a special case of a something more general and if you're always climbing up the tree on to the more general thing you'll eventually wind up with a PhD in computer science... and no code.

However, on the other hand, if we just scrabble along the earth and we never, sort of, poke our head up and look around to see the more general thing we are constantly re-solving the same problems, you're not even recognizing that two different things we solve are both aspects of same thing. So what I try to do is I always try to recognize what that general case is, and then discipline myself not to solve the general case until it's really an imperative but not to be ignorant of the general case.”

On the continuum of thinking in general, more theoretical terms and the more practical nuts and bolts, I’ll admit I err too often on being practical.

I’ve been in the trenches a lot of late so this is a good quote to meditate upon. Especially in a week like this: at the end of an iteration, being asked to “work overtime” to try to get things done and out to customers, it’s very easy to stay in scrabble mode rather than having the disciplines of study and analysis that keep the general case in mind.

}

Saturday, December 05, 2009

Library of the Week: SharpZipLib with Silverlight

{

SharpZipLib has been around in various forms for some time but via this port to Silverlight we have the benefit of leveraging it for compression and decompression in our Silverlight based web applications. Doing a search on sample code gives back a lot of examples (the best of which, IMHO, is from The Codecruncher) of how to use the library but there’s an important difference when it’s used in the Silverlight space: many members of the FileStream are marked as SECURITY CRITICAL and are therefore out of reach in your application. A very simple technique to get around this is to convert the target stream object to a MemoryStream and proceed from there. A series of examples are below, written in simpe form for brevity (reading a file in a single step to a large byte array is a taste thing; of course I’m aware you can read chunks of the file) Here’s a little sample of getting that done:

public MemoryStream GetFileData(FileStream fs) 
{
fs.Seek(0, SeekOrigin.Begin);
byte[] data = new byte[fs.Length];
fs.Read(data, 0, (int)fs.Length);
MemoryStream ms = new MemoryStream(data);
return ms;
}




Here are examples of listing, extracting, and compressing files, respectively:






//open a file dialog, pick a zip and list contents
List entries = new List();
OpenFileDialog ofd = new OpenFileDialog();
if (true == ofd.ShowDialog())
{

using(FileStream fs = ofd.File.OpenRead())
{
ZipFile zip = new ZipFile(GetFileData(fs));
foreach (ZipEntry entry in zip)
{
entries.Add(entry.Name);
}
zipFileListBox.ItemsSource = entries.ToArray();
}








//open a file dialog, pick a *.zip and extract to isolated storage
OpenFileDialog ofd = new OpenFileDialog();
if (true == ofd.ShowDialog())
{
string fiName = ofd.File.Name;
ZipEntry entry;
using(ZipInputStream zis = new ZipInputStream(GetFileData(ofd.File.OpenRead())))
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
string folderForOutput = System.IO.Path.GetFileNameWithoutExtension(ofd.File.Name);
if (!isf.DirectoryExists(folderForOutput)) {
isf.CreateDirectory(folderForOutput);
}

while ((entry = zis.GetNextEntry()) != null)
{
if (isf.FileExists(entry.Name))
{
isf.DeleteFile(entry.Name);
}
long sizeToWrite = entry.Size;
using (FileStream fs = isf.CreateFile(folderForOutput + "/" + entry.Name))
using(StreamWriter sw = new StreamWriter(fs))
{
byte[] data = new byte[sizeToWrite];
int bytesRead = zis.Read(data, 0, data.Length);
if (bytesRead > 0)
{
sw.Write(data);
}
}
}
}
}








//open a file dialog, pick some files and create a *.zip
OpenFileDialog ofd = new OpenFileDialog();
ofd.Multiselect = true;
if (true == ofd.ShowDialog())
{
using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
{
using (FileStream fs = isf.CreateFile("TheZip.zip"))
using (ZipOutputStream zipOut = new ZipOutputStream(fs))
{
foreach (FileInfo selectedFile in ofd.Files) {
byte[] fileData = new byte[selectedFile.Length];
using (FileStream selectedFileStream = selectedFile.OpenRead()) {
selectedFileStream.Read(fileData, 0, fileData.Length);
ZipEntry entry = new ZipEntry(selectedFile.Name);
entry.DateTime = DateTime.Now;
entry.Size = selectedFile.Length;
zipOut.PutNextEntry(entry);
zipOut.Write(fileData, 0, fileData.Length);
}
}
zipOut.Finish();
}
}
}




It must be noted that SharpZipLib is GPL but because of a special clause in the license, you can use it in a “closed source” application as Jon Galloway explains here.



}