Sign in to follow this  
Drakken255

Zip/Unzip Files without .NET 4.5: #ZipLib Not Working

Recommended Posts

Drakken255    173
Hello all,

I need to be able to zip and unzip files that are known to be named oddly, and my current method (SharpZipLib and a recursive zip/unzip wrapper) can't do it right. An example would be "aux.class" which is a reserved file name, so File won't write that. I've currently rigged a bit of a renaming system specifically for this file, but I dont like doing that sort of thing, it's just too messy and inefficient having to do special things for one file.

Next, I've noticed that even though the files now unzip and rezip, there is a difference between the original and the rezip. Currently, both the manually unzipped and the programmatically unzipped folders have the same size, but there is a difference of over 90KB between the original and the rezipped files, when done so programmatically. Any difference in zips is highly unacceptable since it's actually a JAR archive I'm messing with.

There is the possibility that I am missing something, so I'll give the benefit of the doubt and post my wrapper here:

[spoiler]
[code]
using System;
using System.Collections;
using System.IO;
using ICSharpCode.SharpZipLib.Zip;


namespace PatchCraft.Classes
{
public static class ZipUtils
{
public static void ZipFiles(string inputFolderPath, string outputPathAndFile, string password)
{
string[] moddedFileNames = null;
bool fileNamesModded = false;
if (File.Exists(inputFolderPath + @"\changedFiles.zud"))
{
moddedFileNames = File.ReadAllLines(inputFolderPath + @"\changedFiles.zud");
File.Delete(inputFolderPath + @"\changedFiles.zud");
fileNamesModded = true;
}
ArrayList ar = GenerateFileList(inputFolderPath); // generate file list
//int TrimLength = (Directory.GetParent(inputFolderPath)).ToString().Length;
int TrimLength = inputFolderPath.Length;
// find number of chars to remove // from orginal file path
//TrimLength += 1; //remove ‘\’
FileStream ostream;
byte[] obuffer;
string outPath = inputFolderPath + @"\" + outputPathAndFile;
ZipOutputStream oZipStream = new ZipOutputStream(File.Create(outputPathAndFile)); // create zip stream
if (password != null && password != String.Empty)
oZipStream.Password = password;
oZipStream.SetLevel(9); // maximum compression
ZipEntry oZipEntry;
foreach (string Fil in ar) // for each file, generate a zipentry
{
string realFile = Fil;
oZipEntry = new ZipEntry(realFile.Remove(0, TrimLength));
oZipStream.PutNextEntry(oZipEntry);
if (!Fil.EndsWith(@"/")) // if a file ends with ‘/’ its a directory
{
ostream = File.OpenRead(Fil);
obuffer = new byte[ostream.Length];
ostream.Read(obuffer, 0, obuffer.Length);
oZipStream.Write(obuffer, 0, obuffer.Length);
ostream.Close();
ostream.Dispose();
}
oZipEntry = null;
}
oZipStream.Finish();
oZipStream.Close();
oZipStream.Dispose();
ar = null;
}
private static ArrayList GenerateFileList(string Dir)
{
ArrayList files = new ArrayList();
bool Empty = true;
foreach (string file in Directory.GetFiles(Dir)) // add each file in directory
{
files.Add(file);
Empty = false;
}
if (Empty)
{
if (Directory.GetDirectories(Dir).Length == 0)
// if directory is completely empty, add it
{
files.Add(Dir + @"/");
}
}
foreach (string dirs in Directory.GetDirectories(Dir)) // recursive
{
foreach (object obj in GenerateFileList(dirs))
{
files.Add(obj);
}
}
return files; // return file list
}
public static void UnZipFiles(string zipPathAndFile, string outputFolder, string password, bool deleteZipFile)
{
ZipInputStream s = new ZipInputStream(File.OpenRead(zipPathAndFile));
if (password != null && password != String.Empty)
s.Password = password;
ZipEntry theEntry;
string tmpEntry = String.Empty;
while ((theEntry = s.GetNextEntry()) != null)
{
string directoryName = outputFolder;
string fileName = Path.GetFileName(theEntry.Name);
// create directory
if (directoryName != "")
{
Directory.CreateDirectory(directoryName);
}
if (fileName != String.Empty)
{
if (theEntry.Name.IndexOf(".ini") < 0)
{
string fullPath = "";
if (!theEntry.Name.Contains("aux"))
{
fullPath = directoryName + "\\" + theEntry.Name;
}
else
{
fullPath = directoryName + "\\_" + theEntry.Name;
}
fullPath = fullPath.Replace("\\ ", "\\");
string fullDirPath = Path.GetDirectoryName(fullPath);
if (!Directory.Exists(fullDirPath)) Directory.CreateDirectory(fullDirPath);
FileStream streamWriter = null;
streamWriter = File.Create(fullPath);
int size = 2048;
byte[] data = new byte[2048];
while (true)
{
size = s.Read(data, 0, data.Length);
if (size > 0)
{
streamWriter.Write(data, 0, size);
}
else
{
break;
}
}
streamWriter.Close();
streamWriter.Dispose();
}
}
}
s.Close();
s.Dispose();
theEntry = null;
if (deleteZipFile)
File.Delete(zipPathAndFile);
}
}
}
[/code]
[/spoiler]

If my code is correct, then I can't use SharpZipLib. I need something that can zip and unzip files accurately with no difference between the original and the rezip, no matter the file name, so I'm looking to use something else. Anyone have any ideas on what else to try?

UPDATE: I have switched over to DotNetZip and it does FAR better. The JAR (being Minecraft) actually runs now! The problem now is still that aux.class file. Now, when loading a map, the game will crash with "Incompatible magic value 0 in class file aux" or "ClassDefNotFound for aux" which obviously means it is corrupted somehow, but I just don't know what's going on with it. I have narrowed it down to the fact that done manually, the file will use 313 KB zipped, but after programmatical modification, the file will be only 8. 7-Zip strangely enough shows that each has the same unzipped file size... Edited by Drakken255

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this