使用 C# 压缩单个文件
Posted
技术标签:
【中文标题】使用 C# 压缩单个文件【英文标题】:Compress a single file using 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 解决方案,但感谢您的建议。似乎引用答案中的人正在尝试从头开始创建新文件并写入流,但我会尝试从那里找到解决方案。谢谢。
【参考方案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 的引用
更新
另外,请查看 ZipFile 和 ZipArchive 的新 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】:最简单的方法是使用临时文件夹。
用于压缩:
-
创建临时文件夹
将文件移动到文件夹
压缩文件夹
删除文件夹
解压:
-
解压存档
将文件从临时文件夹移动到您的位置
删除临时文件夹
【讨论】:
感谢您的建议。对于任何好奇的人,我正在使用它来添加一个应用程序,该应用程序将 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以上是关于使用 C# 压缩单个文件的主要内容,如果未能解决你的问题,请参考以下文章