How to unzip files in Windows Phone 8

前端 未结 1 1863
我寻月下人不归
我寻月下人不归 2021-01-24 19:23

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

相关标签:
1条回答
  • 2021-01-24 19:58

    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;
        }
    }    
    
    0 讨论(0)
提交回复
热议问题