【问题标题】:Compress a single file using C#使用 C# 压缩单个文件
【发布时间】:2014-09-22 09:48:47
【问题描述】:

我正在使用 .NET 4.5,如果我尝试使用“CreateFromDirectory”压缩整个目录,则 ZipFile 类效果很好。但是,我只想压缩目录中的一个文件。我尝试指向特定文件(文件夹\data.txt),但这不起作用。我考虑了 ZipArchive 类,因为它有一个“CreateEntryFromFile”方法,但似乎这只允许您在现有文件中创建一个条目。

有没有办法简单地压缩一个文件而不创建一个空的压缩文件(这有它的问题),然后使用 ZipArchiveExtension 的“CreateEntryFromFile”方法?

**这也是假设我正在开发一个目前无法使用第三方插件的公司程序。

示例来自:http://msdn.microsoft.com/en-us/library/ms404280%28v=vs.110%29.aspx

        string startPath = @"c:\example\start";
        string zipPath = @"c:\example\result.zip";
        string extractPath = @"c:\example\extract";

        ZipFile.CreateFromDirectory(startPath, zipPath);

        ZipFile.ExtractToDirectory(zipPath, extractPath);

但如果 startPath 为@"c:\example\start\myFile.txt;",则会抛出目录无效的错误。

【问题讨论】:

  • but that doesn't work 什么不起作用?你的代码在哪里?
  • 指向特定文件不适用于“CreateFromDirectory”。我将微软示例添加到原始问题中。
  • 您可以使用 ZipArchive 类创建一个新的 Zip 存档,尽管它并不完全是单行的。请参阅answer here 了解如何操作。 (如果这太麻烦,您可能会考虑使用更好的 3rd-party 库来处理 ZIP,例如DotNetZip
  • 或者您可以将文件移动到临时文件夹进行压缩,并在删除后提取到同一个临时文件夹?最好的解决方案是获得更好的库。
  • @elgonzo 我提到我不能使用 3rd-party 解决方案,但感谢您的建议。似乎引用答案中的人正在尝试从头开始创建新文件并写入流,但我会尝试从那里找到解决方案。谢谢。

标签: c# .net zip zipfile


【解决方案1】:

使用存档中的CreateEntryFromFile 并使用文件或内存流:

如果您可以创建 zip 文件然后添加到其中,请使用文件流:

using (FileStream fs = new FileStream(@"C:\Temp\output.zip",FileMode.Create))
using (ZipArchive arch = new ZipArchive(fs, ZipArchiveMode.Create))
{
    arch.CreateEntryFromFile(@"C:\Temp\data.xml", "data.xml");
}

或者,如果您需要在内存中执行所有操作并在完成后写入文件,请使用内存流:

using (MemoryStream ms = new MemoryStream())
using (ZipArchive arch = new ZipArchive(ms, ZipArchiveMode.Create))
{
    arch.CreateEntryFromFile(@"C:\Temp\data.xml", "data.xml");
}

那你可以write the MemoryStream to a file

using (FileStream file = new FileStream("file.bin", FileMode.Create, System.IO.FileAccess.Write)) {
   byte[] bytes = new byte[ms.Length];
   ms.Read(bytes, 0, (int)ms.Length);
   file.Write(bytes, 0, bytes.Length);
   ms.Close();
}

【讨论】:

  • 这应该是公认的解决方案。虽然 AlexanderBrevig 的解决方案可能有效,但临时创建文件夹以制作 zip 文件涉及许多不必要的额外步骤。 John Koerner 的解决方案更简单,但可能更简单。如果您用 FileStream 代替他的 MemoryStream,则不需要将 MemoryStream 写入磁盘的第二步。也许有我不知道的速度或内存使用优势,但如果最终目标是 ZIP 文件,则直接转到 FileStream 会更好。
  • 仅供参考:使用 ZipArchive 时,需要将 System.IO.Compression 引用添加到您的项目。不仅是System.IO.Compression.FileSystem
【解决方案2】:

使用文件(或任何)流:

using (var zip = ZipFile.Open("file.zip", ZipArchiveMode.Create))
{
    var entry = zip.CreateEntry("file.txt");
    entry.LastWriteTime = DateTimeOffset.Now;

    using (var stream= File.OpenRead(@"c:\path\to\file.txt"))
    using (var entryStream = entry.Open())
        stream.CopyTo(entryStream);
}

或更简单:

// reference System.IO.Compression
using (var zip = ZipFile.Open("file.zip", ZipArchiveMode.Create))
    zip.CreateEntryFromFile("file.txt", "file.txt");

确保添加对 System.IO.Compression 的引用

更新

另外,请查看 ZipFileZipArchive 的新 dotnet API 文档。那里有几个例子。还有一个关于引用System.IO.Compression.FileSystem 以使用ZipFile 的警告。

要使用 ZipFile 类,您必须引用 项目中的 System.IO.Compression.FileSystem 程序集。

【讨论】:

  • 可能是个愚蠢的问题....但是即使在添加 dll 引用之后,ZipArchiveMode 也不能被识别为 System.IO.Compression 命名空间的一部分。我看到它已记录在案,但 VS2012 似乎无法找到它(“当前上下文中不存在名称 'ZipArchiveMode'”)?
  • @Ang 确保添加对 System.IO.Compression 的引用。如果你想使用CreatEntryFromFile,那么还要参考System.IO.Compression.FileSystem。
【解决方案3】:

最简单的方法是使用临时文件夹。

用于压缩:

  1. 创建临时文件夹
  2. 将文件移动到文件夹
  3. 压缩文件夹
  4. 删除文件夹

解压:

  1. 解压存档
  2. 将文件从临时文件夹移动到您的位置
  3. 删除临时文件夹

【讨论】:

  • 感谢您的建议。对于任何好奇的人,我正在使用它来添加一个应用程序,该应用程序将 Lotus Notes 附件作为嵌入式对象移动到 MSWord 文件中,但是原生不支持两种古老的文件类型,因此使用了 zip 解决方案。
  • 更像:先压缩然后解压缩... 好吗? GG
【解决方案4】:

在 .NET 中,有很多方法可以解决单个文件的问题。如果您不想在那里学习所有内容,可以获取一个抽象库,例如 SharpZipLib(长期开源库)、sevenzipsharp(下面需要 7zip 库)或 DotNetZip。

【讨论】:

    【解决方案5】:

    只需使用以下代码压缩文件。

    public void Compressfile()
            {
                 string fileName = "Text.txt";
                 string sourcePath = @"C:\SMSDBBACKUP";
                 DirectoryInfo di = new DirectoryInfo(sourcePath);
                 foreach (FileInfo fi in di.GetFiles())
                 {
                     //for specific file 
                     if (fi.ToString() == fileName)
                     {
                         Compress(fi);
                     }
                 } 
            }
    
    public static void Compress(FileInfo fi)
            {
                // Get the stream of the source file.
                using (FileStream inFile = fi.OpenRead())
                {
                    // Prevent compressing hidden and 
                    // already compressed files.
                    if ((File.GetAttributes(fi.FullName)
                        & FileAttributes.Hidden)
                        != FileAttributes.Hidden & fi.Extension != ".gz")
                    {
                        // Create the compressed file.
                        using (FileStream outFile =
                                    File.Create(fi.FullName + ".gz"))
                        {
                            using (GZipStream Compress =
                                new GZipStream(outFile,
                                CompressionMode.Compress))
                            {
                                // Copy the source file into 
                                // the compression stream.
                                inFile.CopyTo(Compress);
    
                                Console.WriteLine("Compressed {0} from {1} to {2} bytes.",
                                    fi.Name, fi.Length.ToString(), outFile.Length.ToString());
                            }
                        }
                    }
                }
            }
    
        }
    

    【讨论】:

    • 这是 GZIP,不是 ZIP
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多