Scott Hanselman just posted about a case-{in}sensitivity problem he just went through. That reminded me I wanted to talk to you about case-sensitivity in Xceed Zip for .NET and the FileSystem. I remember back in the design days, we debated long and hard on if the FileSystem should be case-sensitive or not. Once we decided to support both, the debate continued about what should be the default behavior.
The conclusions were simple:
- Immitate by default.
- Uniformity within single product.
- Know the differences.
Since System.IO was case-insensitive (and moreover the whole Windows operating system), we had to be case-insensitive by default. Thus, if you have files "first.txt" and "second.TXT" in a folder, the code below will return you two files:
DiskFolder disk = new DiskFolder( @"t:\" );
AbstractFile[] files = disk.GetFiles( false, "*.txt" );
The same way, if you have both files in a zip file, the following code will return both:
ZipArchive zip = new ZipArchive( new DiskFile( @"t:\texts.zip" ) );
AbstractFile[] files = zip.GetFiles( false, "*.txt" );
Now, where it's getting tricky is that you will never have a folder on disk containing both "second.TXT" and "second.txt". The system won't let you create the second one. Thus the following code returns an existing file who's FullName is all lower case, even if the real file has an upper-case extension:
DiskFolder disk = new DiskFolder( @"t:\" );
AbstractFile file1 = disk.GetFile( "second.txt" );
You asked the "Disk" world for file "second.txt", and this world has recognized "second.TXT" as matching your request.
To obey to rule #2, the following code does exactly the same, even though the file stored in the zip file has its extension all upper case:
ZipArchive zip = new ZipArchive( new DiskFile( @"t:\texts.zip" ) );
AbstractFile file2 = zip.GetFile( "second.txt" );
But in a zip file, which can come from a different operating system, you potentially could end up with a zip file containing both. What would happen? I've created such a zip file for our tests, by adding "second.TXT" and "foobar.txt" to a zip file, and hex-editing "foobar" to "second":
second.zip (.23 KB)

When opening this file in WinZip, I can see both files. But when unzipping, it will unzip the first, then try to unzip the second over the first. You just can't unzip both in two separate files. Furthermore, trying to unzip any single one from within the classic view will always unzip both over the same file on disk.
How does Xceed Zip for .NET deal with such zip fles? Try the following code:
ZipArchive zip = new ZipArchive( new DiskFile( @"t:\second.zip" ) );
foreach( AbstractFile file in zip.GetFiles( false ) )
{ Console.WriteLine( file.FullName );
}
The output is:
\second(1).txt
\second.TXT
Any file that case-insensitively matches another file gets appended a number. This is not a perfect solution, as there is never a perfect solution. To support rule #2, DiskFolder and ZippedFolder instances had to behave the same. This post and the documentation tries to address rule #3 
Now, some of you want to always look for exact matches. You simply need to prepend the string mask with a ">", as in "I want a more precise match" (1). The following code will match a single file:
DiskFolder disk = new DiskFolder( @"t:\" );
AbstractFile[] files = disk.GetFiles( false, ">*.txt" );
The idea with System.String filter parameters is that we replace them with a NameFilter, which is the one responsible for that ">" trick. It only works with methods accepting filters (GetFiles, GetFolders, CopyFilesTo, MoveFilesTo). Methods like GetFile can only return a single instance (actually always returns an instance which may exist or not). Those methods return the single and unique AbstractFile matching your string, based on the world this AbstractFolder belongs to.
(1): We actually debated between using "<" as in "match less items" or ">" as in "a more precise match". I think we ended up tossing a coin! 