如何在 Windows Phone 8 中解压文件 [英] How to unzip files in Windows Phone 8

查看:17
本文介绍了如何在 Windows Phone 8 中解压文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在我的 Windows Phone 8 应用程序中解压缩文件?大多数库使用的是 Windows Phone 7,但不是 Windows Phone 8.

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.

甚至 System.IO.Compression.ZipFile 都不存在...

Even System.IO.Compression.ZipFile is not there...

推荐答案

把这段代码放在 Unzipper 类里面

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;
    }
}    

这篇关于如何在 Windows Phone 8 中解压文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆