using ICSharpCode.SharpZipLib.Zip;
// Compresses the supplied memory stream, naming it as zipEntryName, into a zip,
// which is returned as a memory stream or a byte array.
//
public MemoryStream CreateToMemoryStream(MemoryStream memStreamIn, string zipEntryName) {
MemoryStream outputMemStream = new MemoryStream();
ZipOutputStream zipStream = new ZipOutputStream(outputMemStream);
zipStream.SetLevel(3); //0-9, 9 being the highest level of compression
zipStream.Password = "Your password";
ZipEntry newEntry = new ZipEntry(zipEntryName);
newEntry.DateTime = DateTime.Now;
zipStream.PutNextEntry(newEntry);
StreamUtils.Copy(memStreamIn, zipStream, new byte[4096]);
zipStream.CloseEntry();
zipStream.IsStreamOwner = false; // False stops the Close also Closing the underlying stream.
zipStream.Close(); // Must finish the ZipOutputStream before using outputMemStream.
outputMemStream.Position = 0;
return outputMemStream;
// Alternative outputs:
// ToArray is the cleaner and easiest to use correctly with the penalty of duplicating allocated memory.
byte[] byteArrayOut = outputMemStream.ToArray();
// GetBuffer returns a raw buffer raw and so you need to account for the true length yourself.
byte[] byteArrayOut = outputMemStream.GetBuffer();
long len = outputMemStream.Length;
}
using ICSharpCode.SharpZipLib.Core;
using ICSharpCode.SharpZipLib.Zip;
namespace DataReader.zip
{
internal static class Zip1 // SharpZipLib nuget lib, MIT free license
{
public static bool Create(string destZipPath, string folderToCompress, string? password = null, int compressionLevel = 3)
{
bool res;
try
{
var fsOut = File.Create($"{destZipPath}.zip"); // ending '.zip' is a must!
var zipStream = new ZipOutputStream(fsOut);
zipStream.SetLevel(compressionLevel); // 0-9, 9 being the highest level of compression
zipStream.Password = password; // optional. Null is the same as not setting. Required if using AES.
// This setting will strip the leading part of the folder path in the entries, to
// make the entries relative to the starting folder.
// To include the full path for each entry up to the drive root, assign folderOffset = 0.
var folderOffset = folderToCompress.Length + (folderToCompress.EndsWith("\\") ? 0 : 1);
res = CompressFolder(folderToCompress, zipStream, folderOffset);
zipStream.IsStreamOwner = true; // Makes the Close also Close the underlying stream
zipStream.Close();
return res;
}
catch (Exception e)
{
return Console.WriteLine($"{e.Message}: {destZipPath}");
}
}
private static bool CompressFolder(string path, ZipOutputStream zipStream, int folderOffset)
{
try
{
var files = Directory.GetFiles(path);
if (files.Length == 0)
{
Message.Show($"Warning: no files to compress found in folder '{path}'");
return false;
}
foreach (var filename in files)
{
var fi = new FileInfo(filename);
var entryName = filename.Substring(folderOffset); // Makes the name in zip based on the folder
entryName = ZipEntry.CleanName(entryName); // Removes drive from name and fixes slash direction
var newEntry = new ZipEntry(entryName);
newEntry.DateTime = fi.LastWriteTime; // Note the zip format stores 2 second granularity
// Specifying the AESKeySize triggers AES encryption. Allowable values are 0 (off), 128 or 256.
// A password on the ZipOutputStream is required if using AES.
// newEntry.AESKeySize = 256;
// To permit the zip to be unpacked by built-in extractor in WinXP and Server2003, WinZip 8, Java, and other older code,
// you need to do one of the following: Specify UseZip64.Off, or set the Size.
// If the file may be bigger than 4GB, or you do not need WinXP built-in compatibility, you do not need either,
// but the zip will be in Zip64 format which not all utilities can understand.
zipStream.UseZip64 = UseZip64.On;
newEntry.Size = fi.Length;
zipStream.PutNextEntry(newEntry);
// Zip the file in buffered chunks
// the "using" will close the stream even if an exception occurs
var buffer = new byte[4096];
using (var streamReader = File.OpenRead(filename))
{
StreamUtils.Copy(streamReader, zipStream, buffer);
}
zipStream.CloseEntry();
}
return true;
}
catch (Exception e)
{
return Console.WriteLine($"{e.Message}: {destZipPath}");
}
}
}
}
第二个问题:
using Ionic.Zip;
namespace DataReader.zip
{
internal class Zip2 // DotNetZip nuget lib
{
public static bool Create(string destZipPath, string folderToCompress, string? password = null, int compressionLevel = 3)
{
try
{
using ZipFile zip = new();
if (password != null)
zip.Password = password;
zip.CompressionLevel = (Ionic.Zlib.CompressionLevel)compressionLevel;
zip.AddDirectory(folderToCompress);
zip.Save($"{destZipPath}.zip");
return true;
}
catch (Exception e)
{
return Console.WriteLine($"{e.Message}: {destZipPath}");
}
}
}
}
5条答案
按热度按时间ghhaqwfi1#
看看DotNetZip(@AFract在评论中提供了一个新的GitHub链接)
它有相当geat文档,它还允许您在运行时加载dll作为嵌入文件。
oknrviil2#
不幸的是,框架中没有这样的功能。有一种方法可以制作ZIP文件,但没有密码。如果你想在C#中创建密码保护的ZIP文件,我推荐SevenZipSharp。它基本上是7-Zip的托管 Package 。
kninwzqo3#
DotNetZip以一种干净的方式工作得很好。
代码
ecfsfe2w4#
我想增加更多的选择。
对于.NET可以使用SharpZipLib,对于Xamarin可以使用SharpZipLib.Portable。
.NET示例:
更多示例可在here中找到。
如果您可以不使用密码功能,可以提到ZipStorer或
System.IO.Compression
中内置的.NET功能。0pizxfdo5#
我发现有两个选项是可靠的,并且很容易使用,这取决于允许您在项目中使用的许可证类型。
第一个是:
第二个问题:
使用这两个选项,您将创建一个zip文件夹,在其中需要密码才能提取文件(如果您在调用方法时设置了密码)。