Replacement for Compression.dll

Topics: Developer Forum
Jan 18, 2007 at 11:57 PM
Since the thread I posted this originally to concerns 64bit code, I thought I would start a thread with the proper title.

The J# library java.util.zip can be referenced by C# with no problems. I coded up a short demo piece to proof out the concept. I do not know right now what needs to be done to Unbundle an LRN package, so I did not start that part of the work.

The only thing I can positively say about this is that it will compile. I have not put it through its paces.



using System;
using System.Collections;
using java.util;
using java.util.zip;


public class Compression
{
public static void Unzip(string zipFileName, string destinationDir)
{ //zipFileName=Compressed File path
try
{
java.io.FileInputStream fis = new java.io.FileInputStream(zipFileName);
java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(fis);
java.util.zip.ZipEntry ze2;
sbyte[] buf = new sbyte1024;
int len;
string fileName;
while ((ze2 = zis.getNextEntry()) != null)
{
fileName = ze2.getName();
string newpath = System.IO.Path.Combine(destinationDir,
System.IO.Path.GetDirectoryName(fileName));
System.IO.Directory.CreateDirectory(newpath);
fileName = System.IO.Path.Combine(destinationDir, fileName);
java.io.FileOutputStream fos = new java.io.FileOutputStream(fileName);
while ((len = zis.read(buf)) >= 0)
{
fos.write(buf, 0, len);
}
fos.close();
}
zis.close();
fis.close();
}
catch
{

}
}


}

Coordinator
Jan 25, 2007 at 5:35 PM
I'm curious to see how this would work, Kent. I looked a little at this and was a bit concerned over the fact that the java.util.zip classes will only work with the java.io classes (I suppose that only makes logical sense :-) ) so it would mean pulling in a wider set of java APIs into the compression class. I suppose if it's encapsulated inside only the Compression assembly, it's at least as good as native x86 code :-)

Can you take this a little farther? I'd like to get a better feel for what this would look like when it was done.
Feb 8, 2007 at 6:41 AM
Well the example I saw was a C# utility to compress and decompress ZIP files and only called in the java.util.zip classes. I may be able to spend some time taking this a little further in the next few days.

Kent
Feb 19, 2007 at 9:17 PM
Actually the java API classes are very small since they are really interfaces to the standard .NET framework classes and some additional code added in as wellto cover the functionality not supported by the framework. Adding a simple reference to the vjslib .NET component is all that is required.

There are some minor glitches in the code I posted above, but I will post the code when I have it polished a bit more.

Kent
Feb 20, 2007 at 6:54 PM
OK, here is the code I updated and tested last night. When setting this up, you need to reference the .NET assembly vjslib. I have used this code in a small windows app to unzip about 10 SCORM packages without a single problem. It will not currently Unbundle an LRN package since I have yet to find any documentation on doing that. If anyone knows where I can find that documentation I could do more.

Kent


using System;
using System.Collections;
using java.util;
using java.util.zip;

//Compression.cs - a replacement for the Compression.dll in the SLK
// Written by: Kent Ogletree, DotNetSCORM Project
// January 18, 2007
// Updated February 20, 2007 - Kent Ogletree

public class Compression
{
//Constructor
public Compression()
{ }

/// <summary>
/// Unzips a file to the destination directory. If the destination does not exist it will create it.
/// </summary>
/// <remarks>
/// Unzips a file to the destination directory. If the destination does not exist it will create it.
/// <param name="zipFileName">zip file to Unzip.</param>
/// <param name="destinationDir">Folder to Unzip contents to.</param>
public static void Unzip(string zipFileName, string destinationDir)
{ //zipFileName=Compressed File path
try
{
//Verify Zip file exists
if(!System.IO.File.Exists(zipFileName))
throw new System.ArgumentException("Zip file does not exist");

// Make sure the target directory exists, else create it
if(!System.IO.Directory.Exists(destinationDir))
System.IO.Directory.CreateDirectory(destinationDir);

java.io.FileInputStream fis = new java.io.FileInputStream(zipFileName);
java.util.zip.ZipInputStream zis = new java.util.zip.ZipInputStream(fis);
java.util.zip.ZipEntry ze2;
sbyte[] buf = new sbyte1024;
int len;
string fileName;
while ((ze2 = zis.getNextEntry()) != null)
{
fileName = ze2.getName();
string newpath = System.IO.Path.Combine(destinationDir, System.IO.Path.GetDirectoryName(fileName));
if (!System.IO.Directory.Exists(newpath))
System.IO.Directory.CreateDirectory(newpath);

if (!ze2.isDirectory())
{
fileName = System.IO.Path.Combine(destinationDir, fileName);
java.io.FileOutputStream fos = new java.io.FileOutputStream(fileName);
while ((len = zis.read(buf)) >= 0)
{
fos.write(buf, 0, len);
}
fos.close();
}
}
zis.close();
fis.close();
}
catch (Exception e)
{
throw (e);
}

}

/// <summary>
/// Unbundles an LRN package to the destination directory. If the destination does not exist it will create it.
/// </summary>
/// <remarks>
/// Unbundles an LRN package to the destination directory. If the destination does not exist it will create it.
/// <param name="lrnFileName">zip file to Unzip.</param>
/// <param name="destinationDir">Folder to Unzip contents to.</param>
public static void Unbundle(string lrnFileName, string destinationDir)
{
throw new System.InvalidOperationException("Unbundle is currently not supported");
}

}
Feb 20, 2007 at 7:38 PM

The LRM packages are packaged using a kind of multi-part MIME message format. The format is most likely documented in ClassServer's 'Learning Resource Development Guide' (which is part of the SDK)

The above solution for UnZip looks great in so many ways. It is clean and easy to maintain too. The only ramification to ponder about is the new requirement for users to have vsjlib on their machines, I guess.

I have been trying to work on this too and currently have working C# code for UnZip based on JayBeaver's code. This however has the shortcoming of being dependent on 'internal' code.


However, with 2 solutions already for (half) of the problem, we seem to be nearing 64-bit support pretty strongly. :)
Feb 23, 2007 at 10:30 PM
Yes, the J# redistributable would need to be installed before using this, however it does bring many benefits. The first is that the redistributable is free for download and we would not rely on third party components that must be kept hidden.

While looking for something else I found an MSDN Magazine article on this very subject:
http://msdn.microsoft.com/msdnmag/issues/03/06/ZipCompression/

Kent

Mar 6, 2007 at 10:23 PM
It seems to be even easier. I just stumbled across System.IO.Compression. It contains the GZip class to compress and uncompress Zip files!! No J# needed, no fancy third party assemblies, just straight up .NET 2.0.

http://www.geekpedia.com/tutorial191_Unzipping-compressed-files-using-GZipStream.html

Kent
Mar 7, 2007 at 1:50 AM
Will the GZipStream class work ? I think the format it uses is different from the Winzip format. I've also created a utility using the Compression class above and it also worked for me to unzip files.

The problem is, if you want to change the Compression class you need to rebuild the whole solution using the source code. Does anybody could do it successfully ? Found some problems doing that such as
- No private key file for signing asssemblies. So assemblies are marked with Delay sign, but you cannot deploy to GAC like that.
- If you create your own private/public key you have to change a lot of files and assembly info since a lot of the methods or class have a internal modifier and you have to pass the public key.
- Some references in some projects are wrong

So again, did anyone already included the class above into a fully working solution ?
Mar 7, 2007 at 3:18 AM
The Interop Team Blog on MSDN has details about PKZip formatted files:
http://blogs.msdn.com/dotnetinterop/archive/2006/04/05/.NET-System.IO.Compression-and-zip-files.aspx

KentWA
Mar 7, 2007 at 3:30 PM
Hi Kent,

Have you tested your uncompress utility on a 64-bit box ? I could successfully use it on a 32-bit box, but when I tested on a 64-bit it gave me an exception System.BadImageFormatException for the vjslib. I have the .NET 2.0 (x64) and J# redistributable (I guess it's a x32 since I couldn't find a x64 version to download) installed.

Here's the exception...

Unhandled Exception: System.BadImageFormatException: Could not load file or assembly 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. An attempt was made to load a program with an incorrect format.
File name: 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
at Compression.Unzip(String zipFileName, String destinationDir)
at CustomUnzip.Program.Main(String[] args)

Any clues ?
Mar 7, 2007 at 4:07 PM

anoguei,

For the problem concerning the signing of the dlls that are re-built, you can disable Strong name validation for the assembly using sn.exe -Vr *,<public key token>. You will be able to add the assemblies to the GAC this way. However, note, that this it is not a safe workaround in a production environment.



Mar 7, 2007 at 5:32 PM
Thanks VandanaPonnuru,

I thought of disabling strong name verification but the security issue that would cause in a prod environment kept me away from it.
Mar 7, 2007 at 7:43 PM
anoguei, Yes the J# libraries are only x32, which I did not realize when I posted. So that does bring in a new issue.

However the solution from the MSDN Blog posting above does not have a dependance on J# at all. The GZipStream class appears to be supported on both x32 and x64 platforms. I am not sure when I will get some time to see what I can do with the example, but will try to get something together.

Kent


Mar 8, 2007 at 12:55 AM
After a lot of struggle I could recompile the SLK with a new key. I could also rebuild the wsp solution file. I've replaced the Unzip method from the Compression dll by a Unzip based on the GZipStream idea posted above. I could unzip a .zip file in the x64 box using a custom utility that uses the GZipStream. But when trying to uncompress via the new compiled SLK is still not working. I noticed that the .zip file is copied to the temp folder but it's not uncompressed there. I must be missing something. Need to debug it a bit more. At least looks like it's getting there...