以编程方式创建 ZIP 文件

发布于 2024-10-31 08:30:23 字数 2197 浏览 5 评论 0原文

我的应用程序将把大量缓存数据存储到本地存储,以提高性能和断开连接。我尝试使用 SharpZipLib 来压缩创建的缓存文件,但遇到了一些困难。

我可以创建文件,但它是无效的。 Windows的内置zip系统和7-zip都表明该文件无效。当我尝试通过 SharpZipLib 以编程方式打开文件时,出现“错误的中央目录签名”异常。我认为部分问题是我直接从 MemoryStream 创建 zip 文件,因此没有“根”目录。不确定如何使用 SharpZipLib 以编程方式创建一个。

下面的 EntityManager 是 IdeaBlade DevForce 生成的“数据上下文”。它可以将其内容保存到流中,以便序列化到磁盘进行缓存。

这是我的代码:

private void SaveCacheFile(string FileName, EntityManager em)
        {
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(FileName, System.IO.FileMode.CreateNew, isf))
                {
                    MemoryStream inStream = new MemoryStream();
                    MemoryStream outStream = new MemoryStream();
                    Crc32 crc = new Crc32();
                    em.CacheStateManager.SaveCacheState(inStream, false, true);
                    inStream.Position = 0;

                    ZipOutputStream zipStream = new ZipOutputStream(outStream);
                    zipStream.IsStreamOwner = false;
                    zipStream.SetLevel(3);

                    ZipEntry newEntry = new ZipEntry(FileName);
                    byte[] buffer = new byte[inStream.Length];
                    inStream.Read(buffer, 0, buffer.Length);
                    newEntry.DateTime = DateTime.Now;
                    newEntry.Size = inStream.Length;
                    crc.Reset();
                    crc.Update(buffer);
                    newEntry.Crc = crc.Value;
                    zipStream.PutNextEntry(newEntry);
                    buffer = null;

                    outStream.Position = 0;
                    inStream.Position = 0;                   
                    StreamUtils.Copy(inStream, zipStream, new byte[4096]);
                    zipStream.CloseEntry();
                    zipStream.Finish();
                    zipStream.Close();
                    outStream.Position = 0;
                    StreamUtils.Copy(outStream, isfs, new byte[4096]);
                    outStream.Close();    

                }
            }
        }

My application will be storing large amounts of cached data to local storage for performance and disconnected purposes. I have tried to use SharpZipLib to compress the cache files that are created, but I'm having some difficulty.

I can get the file created, but it is invalid. Windows' built-in zip system and 7-zip both indicate that the file is invalid. When I attempt to open the file programmatically through SharpZipLib, I get the exception "Wrong Central Directory signature." I think part of the problem is that I'm creating the zip file directly from a MemoryStream, so there is no "root" directory. Not sure how to create one programmatically with SharpZipLib.

The EntityManager below is the IdeaBlade DevForce-generated "datacontext." It can save its contents to a stream for purposes of serializing to disk for caching.

Here's my code:

private void SaveCacheFile(string FileName, EntityManager em)
        {
            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {
                using (IsolatedStorageFileStream isfs = new IsolatedStorageFileStream(FileName, System.IO.FileMode.CreateNew, isf))
                {
                    MemoryStream inStream = new MemoryStream();
                    MemoryStream outStream = new MemoryStream();
                    Crc32 crc = new Crc32();
                    em.CacheStateManager.SaveCacheState(inStream, false, true);
                    inStream.Position = 0;

                    ZipOutputStream zipStream = new ZipOutputStream(outStream);
                    zipStream.IsStreamOwner = false;
                    zipStream.SetLevel(3);

                    ZipEntry newEntry = new ZipEntry(FileName);
                    byte[] buffer = new byte[inStream.Length];
                    inStream.Read(buffer, 0, buffer.Length);
                    newEntry.DateTime = DateTime.Now;
                    newEntry.Size = inStream.Length;
                    crc.Reset();
                    crc.Update(buffer);
                    newEntry.Crc = crc.Value;
                    zipStream.PutNextEntry(newEntry);
                    buffer = null;

                    outStream.Position = 0;
                    inStream.Position = 0;                   
                    StreamUtils.Copy(inStream, zipStream, new byte[4096]);
                    zipStream.CloseEntry();
                    zipStream.Finish();
                    zipStream.Close();
                    outStream.Position = 0;
                    StreamUtils.Copy(outStream, isfs, new byte[4096]);
                    outStream.Close();    

                }
            }
        }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

仅此而已 2024-11-07 08:30:23

直接从内存创建 zip 文件不是您的问题。 SharpZipLib 使用 ZipEntry 构造函数中的参数来确定路径,并且不关心该路径是否有子目录。

using (ZipOutputStream zipStreamOut = new ZipOutputStream(outputstream))
{
    zipStreamOut.PutNextEntry(new ZipEntry("arbitrary.ext"));
    zipstreamOut.Write(mybytearraydata, 0, mybytearraydata.Length);
    zipStreamOut.Finish();
    //Line below needed if outputstream is a MemoryStream and you are
    //passing it to a function expecting a stream.
    outputstream.Position = 0;

    //DoStuff.  Optional; Not necessary if e.g., outputstream is a FileStream.
}

Creating a zip file straight from memory is not your problem. SharpZipLib uses the parameter in the ZipEntry constructor to determine the path, and does not care if that path has subdirectories or not.

using (ZipOutputStream zipStreamOut = new ZipOutputStream(outputstream))
{
    zipStreamOut.PutNextEntry(new ZipEntry("arbitrary.ext"));
    zipstreamOut.Write(mybytearraydata, 0, mybytearraydata.Length);
    zipStreamOut.Finish();
    //Line below needed if outputstream is a MemoryStream and you are
    //passing it to a function expecting a stream.
    outputstream.Position = 0;

    //DoStuff.  Optional; Not necessary if e.g., outputstream is a FileStream.
}
居里长安 2024-11-07 08:30:23

删除 outStream.Position = 0; 就可以了。

Remove outStream.Position = 0; and it works.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文