上一次,筆者介紹了如何使用.NET Framework 內建的 Zip 壓縮功能,但上次只提到如何壓縮檔案,未提到如何解壓縮檔案
前言
上一次,筆者介紹了「如何使用 .NET Framework 內建的 zip 壓縮功能」,但上次只提到如何壓縮檔案,未提到如何解壓縮檔案,今天筆者就再來補足如何使用內建 ZipArchive 解壓縮檔案。
在前一篇文章中,筆者說明了 ZipArchive 類別的用法,以及 ZipArchiveModel 提供的三種設定方式,現在,我們要解壓縮檔案只要使用第 2. Read 方式即可。由於程式碼中使用的順序性幾乎都相同,而且前篇文章中已經說明得相當清楚,所以這邊筆者就使用一張「壓縮檔案」與「解壓縮檔案」的比較圖給讀者來參考,如下:
從上圖我們可以輕易的瞭解壓縮與解壓縮處理的方式的不同之處,也可以發現程序其實是相同的,
第一個、FileStream 改變為「開啟Zip檔案」
第二個、原本是 CreateNew 的 ZipArchive 變成 Read 方式
第三個、原本是在現有 ZipArchive 中 Create 一個 ZipArchive 壓縮檔案則改變為讀取所有 Entries
第四個、原本是建立 ZipEntry 改變為讀取現有 Zip 檔案中要解壓縮的那個檔案的 Entry
第五個、原本是將 byte[] 資訊寫入 ZipEntry 中,改變為從 ZipEntry 讀取出來的 stream 轉成 byte[] 後寫入實體檔案 (解壓縮)
另外,如果您需要一次解壓縮多個檔案,您可以在取得所有 Entries 的地方 「archive.Entries 」(上方第三個步驟)改以回圈方式,並重複「第四個」、「第五個」步驟就可以將 Entries 內所有檔案解壓縮出來。
第一篇文章加上第二篇文章所有完整的程式碼如下(使用 LINQPad):
public class ZipArchiveFile
{
/// 建立壓縮檔案
/// </summary>
/// <param name="sourceFile">來源 Excel 檔案</param>
/// <param name="targetFile">目標 Zip 檔案</param>
/// <returns>The target Zip FileName</returns>
public static string CreateZipArchiveByExcel(string sourceFile)
{
bool result = false;
string workPath = Path.GetDirectoryName(sourceFile);
string createEntryFileName = Path.GetFileName(sourceFile);
string targetZipFileName = string.Format("{0}{1}", Path.GetFileNameWithoutExtension(sourceFile), ".zip");
string distinationFile = Path.Combine(workPath, targetZipFileName);
FileStream f = new FileStream(sourceFile, FileMode.Open, FileAccess.Read);
try
{
using (var fileStream = new FileStream(distinationFile, FileMode.CreateNew))
{
using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Create, true))
{
byte[] xlsxBytes = BinaryUtil.BinaryReadToEnd(f);
var zipArchiveEntry = archive.CreateEntry(createEntryFileName, CompressionLevel.Fastest);
using (var zipStream = zipArchiveEntry.Open())
{
zipStream.Write(xlsxBytes, 0, xlsxBytes.Length);
}
result = true;
}
}
}
finally
{
f.Close();
}
return distinationFile;
}
public static string GetFileFromZipArchive(string sourceFile, string extractEntryFileName)
{
string workPath = Path.GetDirectoryName(sourceFile);
string distinationFile = Path.Combine(workPath, contentEntryFileName);
FileStream f = new FileStream(distinationFile, FileMode.CreateNew, FileAccess.ReadWrite);
try
{
using (var fileStream = new FileStream(sourceFile, FileMode.Open))
{
using (var archive = new ZipArchive(fileStream, ZipArchiveMode.Read, true))
{
var zipArchiveEntry = archive.Entries
.Where(c => c.Name == extractEntryFileName)
.FirstOrDefault();
if(zipArchiveEntry == null)
return;
using (var zipStream = zipArchiveEntry.Open())
{
BinaryWriter bw = new BinaryWriter(f);
byte[] xlsxBytes = BinaryUtil.BinaryReadToEnd(zipStream);
bw.Write(xlsxBytes);
bw.Close();
}
}
}
}
finally
{
f.Close();
}
return distinationFile;
}
}
class BinaryUtil
{
public static byte[] BinaryReadToEnd(Stream stream)
{
long originalPosition = 0;
if (stream.CanSeek)
{
originalPosition = stream.Position;
stream.Position = 0;
}
try
{
byte[] readBuffer = new byte[4096];
int totalBytesRead = 0;
int bytesRead;
while ((bytesRead = stream.Read(readBuffer, totalBytesRead, readBuffer.Length - totalBytesRead)) > 0)
{
totalBytesRead += bytesRead;
if (totalBytesRead == readBuffer.Length)
{
int nextByte = stream.ReadByte();
if (nextByte != -1)
{
byte[] temp = new byte[readBuffer.Length * 2];
Buffer.BlockCopy(readBuffer, 0, temp, 0, readBuffer.Length);
Buffer.SetByte(temp, totalBytesRead, (byte)nextByte);
readBuffer = temp;
totalBytesRead++;
}
}
}
byte[] buffer = readBuffer;
if (readBuffer.Length != totalBytesRead)
{
buffer = new byte[totalBytesRead];
Buffer.BlockCopy(readBuffer, 0, buffer, 0, totalBytesRead);
}
return buffer;
}
finally
{
if (stream.CanSeek)
{
stream.Position = originalPosition;
}
}
}
}
void Main()
{
string sourceFile = @"D:\Gelis Documents\客戶提供資料\Summary.zip";
string extractFileName = ZipArchiveFile.GetFileFromZipArchive(sourceFile, "Summary.xlsx");
}
所以,我只要使用上面 「Main」中的程式碼,即可將 Summary.zip 中的 Summary.xlsx 解壓縮出來。
結語:
下一次讀者在 .net 的程式中如需要 Zip 壓縮與解壓縮功能時,可以試試看 ZipArchive,完全不需要安裝任何套件,而且壓縮與解壓縮效率極快,不失為一個好選擇喔。
簽名:
學習是一趟奇妙的旅程
這當中,有辛苦、有心酸、也有成果。有時也會有瓶頸。要能夠繼續勇往直前就必須保有一顆最熱誠的心。
軟體開發之路(FB 社團):https://www.facebook.com/groups/361804473860062/
Gelis 程式設計訓練營(粉絲團):https://www.facebook.com/gelis.dev.learning/
如果文章對您有用,幫我點一下讚,或是點一下『我要推薦』,這會讓我更有動力的為各位讀者撰寫下一篇文章。
非常謝謝各位的支持與愛護,小弟在此位各位說聲謝謝!!! ^_^