当文件当前在内存中时,是否有办法创建包含多个文件的Zip归档文件?我想要保存的文件实际上只是文本,并存储在我的应用程序的字符串类中。但我想将多个文件保存在一个独立的归档文件中。他们都可以成为档案的根源。在C#中的多个内存文件中创建Zip归档文件
这将是很好能够使用SharpZipLib做到这一点。
当文件当前在内存中时,是否有办法创建包含多个文件的Zip归档文件?我想要保存的文件实际上只是文本,并存储在我的应用程序的字符串类中。但我想将多个文件保存在一个独立的归档文件中。他们都可以成为档案的根源。在C#中的多个内存文件中创建Zip归档文件
这将是很好能够使用SharpZipLib做到这一点。
为此,使用ZipEntry
和PutNextEntry()
。下面显示了如何做到这一点的文件,但在内存中的对象只使用一个MemoryStream
FileStream fZip = File.Create(compressedOutputFile);
ZipOutputStream zipOStream = new ZipOutputStream(fZip);
foreach (FileInfo fi in allfiles)
{
ZipEntry entry = new ZipEntry((fi.Name));
zipOStream.PutNextEntry(entry);
FileStream fs = File.OpenRead(fi.FullName);
try
{
byte[] transferBuffer[1024];
do
{
bytesRead = fs.Read(transferBuffer, 0, transferBuffer.Length);
zipOStream.Write(transferBuffer, 0, bytesRead);
}
while (bytesRead > 0);
}
finally
{
fs.Close();
}
}
zipOStream.Finish();
zipOStream.Close();
是的,你可以使用SharpZipLib来做到这一点 - 当你需要提供一个流写入,使用MemoryStream
。
使用StringReader来读取字符串对象并将它们公开为Stream。
这应该很容易将它们提供给您的zip构建代码。
注意这个答案已经过时;自.NET 4.5开始,ZipArchive
类允许在内存中压缩文件。有关如何使用它,请参阅johnny 5's answer below。
你也可以做到这一点有点不同,采用序列化对象来存储所有字符串
[Serializable]
public class MyStrings {
public string Foo { get; set; }
public string Bar { get; set; }
}
然后,你可以把它序列化到一个流保存它。
为了节省空间,你可以使用GZipStream(来自System.IO.Compression)来压缩它。 (注意:GZip是流压缩,而不是多个文件的存档)。
也就是说,如果您需要的实际上是保存数据,而不是以其他软件的特定格式压缩几个文件。 此外,这将允许您保存除字符串以外的更多类型的数据。
使用SharpZipLib这个看起来很复杂。这在DotNetZip中容易得多。在V1.9,代码看起来是这样的:上述
using (ZipFile zip = new ZipFile())
{
zip.AddEntry("Readme.txt", stringContent1);
zip.AddEntry("readings/Data.csv", stringContent2);
zip.AddEntry("readings/Index.xml", stringContent3);
zip.Save("Archive1.zip");
}
该代码假定的StringContent {1,2,3}中包含的数据将被存储在zip存档文件(或条目)。第一个条目是“Readme.txt”,它存储在zip存档的顶层“目录”中。接下来的两个条目存储在zip存档的“阅读”目录中。
字符串以默认编码进行编码。 AddEntry()有一个重载,这里没有显示,它允许你明确指定要使用的编码。
如果您的流中或字节数组中的内容不是字符串,那么接受这些类型的AddEntry()会有重载。还有一些重载接受了一个Write委托,这是你调用的将数据写入zip的方法。例如,这适用于将DataSet轻松保存到zip文件中。
DotNetZip是免费且开源的。
我碰到过这样的问题,使用MSDN例子中,我创建了这个类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO.Packaging;
using System.IO;
public class ZipSticle
{
Package package;
public ZipSticle(Stream s)
{
package = ZipPackage.Open(s, FileMode.Create);
}
public void Add(Stream stream, string Name)
{
Uri partUriDocument = PackUriHelper.CreatePartUri(new Uri(Name, UriKind.Relative));
PackagePart packagePartDocument = package.CreatePart(partUriDocument, "");
CopyStream(stream, packagePartDocument.GetStream());
stream.Close();
}
private static void CopyStream(Stream source, Stream target)
{
const int bufSize = 0x1000;
byte[] buf = new byte[bufSize];
int bytesRead = 0;
while ((bytesRead = source.Read(buf, 0, bufSize)) > 0)
target.Write(buf, 0, bytesRead);
}
public void Close()
{
package.Close();
}
}
然后,您可以使用它像这样:
FileStream str = File.Open("MyAwesomeZip.zip", FileMode.Create);
ZipSticle zip = new ZipSticle(str);
zip.Add(File.OpenRead("C:/Users/C0BRA/SimpleFile.txt"), "Some directory/SimpleFile.txt");
zip.Add(File.OpenRead("C:/Users/C0BRA/Hurp.derp"), "hurp.Derp");
zip.Close();
str.Close();
可以传递一个MemoryStream
(或任何Stream
)至ZipSticle.Add
如:
FileStream str = File.Open("MyAwesomeZip.zip", FileMode.Create);
ZipSticle zip = new ZipSticle(str);
byte[] fileinmem = new byte[1000];
// Do stuff to FileInMemory
MemoryStream memstr = new MemoryStream(fileinmem);
zip.Add(memstr, "Some directory/SimpleFile.txt");
memstr.Close();
zip.Close();
str.Close();
此功能应创建从数据流的字节数组:我已经创建了一个简单的接口,用于通过添加MemoryStream
S作为不同的Excel文件的源文件处理为简单起见
public interface IHasDocumentProperties
{
byte[] Content { get; set; }
string Name { get; set; }
}
public void CreateZipFileContent(string filePath, IEnumerable<IHasDocumentProperties> fileInfos)
{
using (var memoryStream = new MemoryStream())
using (var zipArchive = new ZipArchive(memoryStream, ZipArchiveMode.Create, true))
{
foreach(var fileInfo in fileInfos)
{
var entry = zipArchive.CreateEntry(fileInfo.Name);
using (var entryStream = entry.Open())
{
entryStream.Write(fileInfo.Content, 0, fileInfo.Content.Length);
}
}
}
using (var fileStream = new FileStream(filePath, FileMode.OpenOrCreate, System.IO.FileAccess.Write))
{
memoryStream.CopyTo(fileStream);
}
}
。当我下载zip文件时,文件中没有任何内容。这可能是我们试图通过AJAX创建和下载文件的方式。
为了得到Zip中包含的不同Excel文件的内容,我必须将每个文件添加为byte[]
。
using (var memoryStream = new MemoryStream())
using (var zip = new ZipFile())
{
zip.AddEntry("Excel File 1.xlsx", excelFileStream1.ToArray());
zip.AddEntry("Excel File 2.xlsx", excelFileStream2.ToArray());
// Keep the file off of disk, and in memory.
zip.Save(memoryStream);
}
您可以在`zipOStream`上使用'using()'而不是`Close()`吗? – 2008-12-21 03:47:46
是的,ZipOutputStream是一次性的 – Mike 2009-08-10 01:19:32