Is it possible to unzip files on my application which is on Windows Phone 8? Most libs are using Windows Phone 7 but not Windows Phone 8.
Even System.IO.Compressio
Put this code inside Unzipper class like this
public sealed class UnZipper : IDisposable
{
private Stream stream;
private List<FileEntry> fileEntries;
/// <summary>
/// Class used for storing file entry information when
/// parsing the central file directory.
/// </summary>
private class FileEntry
{
public string Filename;
public int FileStart;
public int CompressedSize;
public int UncompressedSize;
public int CRC32;
}
/// <summary>
/// Initializes a new instance of the <see cref="UnZipper"/> class.
/// </summary>
/// <param name="zipFileStream">The zip file stream.</param>
public UnZipper(Stream zipFileStream)
{
if (!zipFileStream.CanSeek)
throw new NotSupportedException("zip stream must be seekable");
this.stream = zipFileStream;
}
/// <summary>
/// Gets the file stream for the specified file. Returns null if the file could not be found.
/// </summary>
/// <param name="filename">The filename.</param>
/// <returns>Stream to file inside zip stream</returns>
public Stream GetFileStream(string filename)
{
if (fileEntries == null)
fileEntries = ParseCentralDirectory(); //We need to do this in case the zip is in a format Silverligth doesn't like
long position = this.stream.Position;
this.stream.Seek(0, SeekOrigin.Begin);
Uri fileUri = new Uri(filename, UriKind.Relative);
StreamResourceInfo info = new StreamResourceInfo(this.stream, null);
StreamResourceInfo stream = System.Windows.Application.GetResourceStream(info, fileUri);
this.stream.Position = position;
if (stream != null)
return stream.Stream;
return null;
}
/// <summary>
/// Gets a list of file names embedded in the zip file.
/// </summary>
/// <param name="stream">The stream for a zip file.</param>
/// <returns>List of file names</returns>
public IEnumerable<string> FileNamesInZip()
{
//get
//{
if (fileEntries == null)
fileEntries = ParseCentralDirectory();
foreach (FileEntry entry in fileEntries)
//Ignore folders and "hidden" MacOS folders
if (!entry.Filename.EndsWith("/") && !entry.Filename.StartsWith("__MACOSX/"))
yield return entry.Filename;
//}
}
/// <summary>
/// Gets a list of directories embedded in the zip file
/// </summary>
public IEnumerable<string> DirectoriesInZip
{
get
{
if (fileEntries == null)
fileEntries = ParseCentralDirectory();
foreach (FileEntry entry in fileEntries)
//Ignore files and special MacOS folders
if (entry.Filename.EndsWith("/") && !entry.Filename.StartsWith("__MACOSX/"))
yield return entry.Filename;
}
}
private List<FileEntry> ParseCentralDirectory()
{
BinaryReader reader = new BinaryReader(this.stream);
List<FileEntry> entries = new List<FileEntry>();
reader.BaseStream.Seek(-4, SeekOrigin.End);
while (reader.ReadInt32() != 101010256)
{
reader.BaseStream.Seek(-5, SeekOrigin.Current);
}
reader.BaseStream.Seek(6, SeekOrigin.Current);
short entryCount = reader.ReadInt16();
int directorySize = reader.ReadInt32();
int directoryStart = reader.ReadInt32();
reader.BaseStream.Seek(directoryStart, SeekOrigin.Begin);
bool needsFixing = false;
for (int i = 0; i < entryCount; i++)
{
int headerSignature = reader.ReadInt32();
if (headerSignature == 33639248) //Central directory file header signature
{
reader.BaseStream.Seek(4, SeekOrigin.Current);
byte flag = reader.ReadByte();
if ((flag & 8) > 0) //Silverlight doesn't like this format. We'll "fix it" further below
{
needsFixing = true;
}
reader.BaseStream.Seek(7, SeekOrigin.Current);
int crc32 = reader.ReadInt32();
int compressedSize = reader.ReadInt32();
int unCompressedSize = reader.ReadInt32();
short fileNameLenght = reader.ReadInt16();
short extraFieldLength = reader.ReadInt16();
short fileCommentLength = reader.ReadInt16();
reader.BaseStream.Seek(8, SeekOrigin.Current);
int fileStart = reader.ReadInt32();
string filename = new string(reader.ReadChars(fileNameLenght));
entries.Add(new FileEntry()
{
Filename = filename,
FileStart = fileStart,
CRC32 = crc32,
CompressedSize = compressedSize,
UncompressedSize = unCompressedSize
});
reader.BaseStream.Seek(extraFieldLength + fileCommentLength, SeekOrigin.Current);
}
}
if (needsFixing)
{
//We are using a zipformat that Silverlight doesn't like.
//Zipfiles where the file size is reported after the compressed data
//is a no-go, so we rebuild the header and report the information there.
MemoryStream newZip = new MemoryStream();
BinaryWriter writer = new BinaryWriter(newZip);
//Rebuild file entries
foreach (FileEntry entry in entries)
{
FileEntry e = entry;
reader.BaseStream.Seek(entry.FileStart, SeekOrigin.Begin);
e.FileStart = (int)writer.BaseStream.Position;
CopyBytes(reader, writer, 6);
byte flag = reader.ReadByte();
writer.Write((byte)(247 & flag)); //set 3rd bit to 0 to indicate the new format
CopyBytes(reader, writer, 7);
writer.Write(entry.CRC32); //Update CRC
writer.Write(entry.CompressedSize); //Update Compressed size
writer.Write(entry.UncompressedSize); //Update Uncompressed size
writer.Write((short)entry.Filename.Length);
reader.BaseStream.Seek(14, SeekOrigin.Current);
short fieldLength = reader.ReadInt16();
writer.Write(fieldLength);
CopyBytes(reader, writer, entry.Filename.Length + fieldLength + entry.CompressedSize);
}
//Rebuild directory
reader.BaseStream.Seek(directoryStart, SeekOrigin.Begin);
for (int i = 0; i < entryCount; i++)
{
CopyBytes(reader, writer, 8);
byte flag = reader.ReadByte();
writer.Write((byte)(247 & flag)); //set 3rd bit to 0 to indicate the new format
CopyBytes(reader, writer, 19);
short filenamelength = reader.ReadInt16();
writer.Write(filenamelength);
short extrafieldlength = reader.ReadInt16();
writer.Write(extrafieldlength);
short filecommentlength = reader.ReadInt16();
writer.Write(filecommentlength);
CopyBytes(reader, writer, 8);
writer.Write(entries[i].FileStart);
reader.BaseStream.Seek(4, SeekOrigin.Current);
CopyBytes(reader, writer, filenamelength + extrafieldlength + filecommentlength);
}
CopyBytes(reader, writer, (int)(reader.BaseStream.Length - reader.BaseStream.Position));
this.stream = newZip; //Replace stream with new stream
}
return entries;
}
private static void CopyBytes(BinaryReader input, BinaryWriter output, int count)
{
for (int i = 0; i < count; i++)
{
output.Write(input.ReadByte());
}
}
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing,
/// or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
if (stream != null)
stream.Dispose();
}
#endregion
}
and use this code where you want to unzip your file:
IsolatedStorageFile myIsolatedStorage = IsolatedStorageFile.GetUserStoreForApplication();
using (IsolatedStorageFileStream fileStream = myIsolatedStorage.OpenFile(yourFileName, FileMode.Open, FileAccess.ReadWrite))
{
UnZipper unzip = new UnZipper(fileStream);
foreach (string filename in unzip.FileNamesInZip())
{
string FileName = filename;
}
}