SharpZipLib :将单个文件压缩为单个压缩文件

发布于 2024-10-14 12:29:48 字数 2437 浏览 7 评论 0原文

我目前正在 .NET 2.0 下使用 SharpZipLib,通过它我需要将单个文件压缩为单个压缩存档。为了做到这一点,我目前正在使用以下内容:

string tempFilePath = @"C:\Users\Username\AppData\Local\Temp\tmp9AE0.tmp.xml";
string archiveFilePath = @"C:\Archive\Archive_[UTC TIMESTAMP].zip";

FileInfo inFileInfo = new FileInfo(tempFilePath);
ICSharpCode.SharpZipLib.Zip.FastZip fZip = new ICSharpCode.SharpZipLib.Zip.FastZip();
fZip.CreateZip(archiveFilePath, inFileInfo.Directory.FullName, false, inFileInfo.Name);

这完全可以正常工作,但是在测试时我遇到了一个小问题。假设我的临时目录(即包含未压缩的输入文件的目录)包含以下文件:

tmp9AE0.tmp.xml //The input file I want to compress
xxx_tmp9AE0.tmp.xml // Some other file
yyy_tmp9AE0.tmp.xml // Some other file
wibble.dat // Some other file

当我运行压缩时,所有 .xml 文件都包含在压缩存档中。其原因在于传递给 CreateZip 方法的最终 fileFilter 参数。 SharpZipLib 正在执行模式匹配,并且还会选取前缀为 xxx_yyy_ 的文件。我想它也会拾取任何后缀的东西。

那么问题是,如何使用 SharpZipLib 压缩单个文件?然后,也许问题是我如何格式化该 fileFilter ,以便匹配只能选取我想要压缩的文件,而不能选取其他文件。

顺便说一句,有什么理由为什么 System.IO.Compression 不包含 ZipStream 类? (它只支持 GZipStream)

编辑:解决方案(源自 Hans Passant 接受的答案)

这是我实现的压缩方法:

private static void CompressFile(string inputPath, string outputPath)
{
    FileInfo outFileInfo = new FileInfo(outputPath);
    FileInfo inFileInfo = new FileInfo(inputPath);

    // Create the output directory if it does not exist
    if (!Directory.Exists(outFileInfo.Directory.FullName))
    {
        Directory.CreateDirectory(outFileInfo.Directory.FullName);
    }

    // Compress
    using (FileStream fsOut = File.Create(outputPath))
    {
        using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipStream = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(fsOut))
        {
            zipStream.SetLevel(3);

            ICSharpCode.SharpZipLib.Zip.ZipEntry newEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(inFileInfo.Name);
            newEntry.DateTime = DateTime.UtcNow;
            zipStream.PutNextEntry(newEntry);

            byte[] buffer = new byte[4096];
            using (FileStream streamReader = File.OpenRead(inputPath))
            {
                ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(streamReader, zipStream, buffer);
            }

            zipStream.CloseEntry();
            zipStream.IsStreamOwner = true;
            zipStream.Close();
        }
    }
}

I am currently working with SharpZipLib under .NET 2.0 and via this I need to compress a single file to a single compressed archive. In order to do this I am currently using the following:

string tempFilePath = @"C:\Users\Username\AppData\Local\Temp\tmp9AE0.tmp.xml";
string archiveFilePath = @"C:\Archive\Archive_[UTC TIMESTAMP].zip";

FileInfo inFileInfo = new FileInfo(tempFilePath);
ICSharpCode.SharpZipLib.Zip.FastZip fZip = new ICSharpCode.SharpZipLib.Zip.FastZip();
fZip.CreateZip(archiveFilePath, inFileInfo.Directory.FullName, false, inFileInfo.Name);

This works exactly (ish) as it should, however while testing I have encountered a minor gotcha. Lets say that my temp directory (i.e. the directory that contains the uncompressed input file) contains the following files:

tmp9AE0.tmp.xml //The input file I want to compress
xxx_tmp9AE0.tmp.xml // Some other file
yyy_tmp9AE0.tmp.xml // Some other file
wibble.dat // Some other file

When I run the compression all the .xml files are included in the compressed archive. The reason for this is because of the final fileFilter parameter passed to the CreateZip method. Under the hood SharpZipLib is performing a pattern match and this also picks up the files prefixed with xxx_ and yyy_. I assume it would also pick up anything postfixed as well.

So the question is, how can I compress a single file with SharpZipLib? Then again maybe the question is how can I format that fileFilter so that the match can only ever pick up the file I want to compress and nothing else.

As an aside, is there any reason as to why System.IO.Compression not include a ZipStream class? (It only supports GZipStream)

EDIT : Solution (Derived from accepted answer from Hans Passant)

This is the compression method I implemented:

private static void CompressFile(string inputPath, string outputPath)
{
    FileInfo outFileInfo = new FileInfo(outputPath);
    FileInfo inFileInfo = new FileInfo(inputPath);

    // Create the output directory if it does not exist
    if (!Directory.Exists(outFileInfo.Directory.FullName))
    {
        Directory.CreateDirectory(outFileInfo.Directory.FullName);
    }

    // Compress
    using (FileStream fsOut = File.Create(outputPath))
    {
        using (ICSharpCode.SharpZipLib.Zip.ZipOutputStream zipStream = new ICSharpCode.SharpZipLib.Zip.ZipOutputStream(fsOut))
        {
            zipStream.SetLevel(3);

            ICSharpCode.SharpZipLib.Zip.ZipEntry newEntry = new ICSharpCode.SharpZipLib.Zip.ZipEntry(inFileInfo.Name);
            newEntry.DateTime = DateTime.UtcNow;
            zipStream.PutNextEntry(newEntry);

            byte[] buffer = new byte[4096];
            using (FileStream streamReader = File.OpenRead(inputPath))
            {
                ICSharpCode.SharpZipLib.Core.StreamUtils.Copy(streamReader, zipStream, buffer);
            }

            zipStream.CloseEntry();
            zipStream.IsStreamOwner = true;
            zipStream.Close();
        }
    }
}

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

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

发布评论

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

评论(1

留一抹残留的笑 2024-10-21 12:29:48

这是一个 XY 问题,只是不要使用 FastZip。请按照此网页上的第一个示例进行操作,以避免发生意外。

This is an XY problem, just don't use FastZip. Follow the first example on this web page to avoid accidents.

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