當文件當前在內存中時,是否有辦法創建包含多個文件的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