C# 用GZipStream 壓縮流來壓縮和解壓檔案
阿新 • • 發佈:2019-01-01
最近在用c#做一些工作,其中需要把檔案進行壓縮和解壓。
有很多種方法,其中比較成熟的就是用別人的類。
可以參考部落格c#壓縮檔案
比較簡單的方式就是用流壓縮,將要寫入的資料變成位元組型陣列,直接寫入流中即可。
程式碼如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 檔案流
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string s = "壓縮檔案實驗";
SaveFileDialog sf = new SaveFileDialog()
{
//設定檔案儲存型別
Filter = "zif檔案|*.zif|所有檔案|*.*",
//如果使用者沒有輸入副檔名,自動追加字尾
AddExtension = true,
//設定標題
Title = "存檔案",
//設定預設檔案型別顯示順序
FilterIndex = 1,
//儲存對話方塊是否記憶上次開啟的目錄
RestoreDirectory = true
};
//如果使用者點選了儲存按鈕
if (sf.ShowDialog() == DialogResult.OK)
{
//例項化一個檔案流--->與寫入檔案相關聯
FileStream fs = new FileStream(sf.FileName, FileMode.Create);
//將字串轉成位元組陣列
var bytes = System.Text.Encoding.Default.GetBytes(s);
//開始寫入(直接寫入檔案了)
//fs.Write(bytes , 0, bytes .Length);
using (GZipStream zipStream = new GZipStream(fs, CompressionMode.Compress)) //代開壓縮檔案流
{
zipStream.Write(bytes, 0, bytes.Length); //寫入壓縮檔案
MessageBox.Show("壓縮成功!");
}
}
}
//解壓寫的不好
private void button2_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog()
{
Filter = "壓縮 files (*.zif)|*.zif|All files (*.*)|*.*"//檔案過濾選擇
};
if (ofd.ShowDialog() == DialogResult.OK)
{
using (FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read))
{
using (GZipStream zipStream = new GZipStream(fs, CompressionMode.Decompress))
{
int bytesRead;
byte[] bytes = new byte[1024*1024*4]; //超大陣列,先把資料全部複製出來。
while ((bytesRead = zipStream.Read(bytes, 0, bytes.Length)) > 0)//bytetesRead是讀出來的位元組數
{
try
{
byte[] longbindata = new byte[bytesRead];
Array.Copy(bytes, 0, longbindata, 0, bytesRead);
System.Diagnostics.Trace.WriteLine(longbindata[0].ToString());
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(ex.Message);
}
}
MessageBox.Show("解壓成功!");
//}
}
}
}
}
}
上次那個解壓操作需要設定一個超大陣列,這簡直就是不人性化呀,查詢了很久,找到另外一種方法:
第一個函式,將流轉成位元組陣列:
public byte[] StreamToBytes(Stream stream)
{
byte[] bytes = new byte[stream.Length];
stream.Read(bytes, 0, bytes.Length);
// 設定當前流的位置為流的開始
stream.Seek(0, SeekOrigin.Begin);
return bytes;
}
第二個函式,將流轉成的位元組陣列傳入以下函式,則可以返回解壓之後的位元組陣列:
public static byte[] Decompress(byte[] bytes)
{
using (var compressStream = new MemoryStream(bytes))
{
using (var zipStream = new GZipStream(compressStream, CompressionMode.Decompress))
{
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}
}
}
所以解壓過程就很人性化:data即是所需要的陣列。
private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog()
{
Filter = "壓縮 files (*.zif)|*.zif|All files (*.*)|*.*"//檔案過濾選擇
};
if (ofd.ShowDialog() == DialogResult.OK)
{
byte[] data = null;
using (FileStream fs = new FileStream(ofd.FileName, FileMode.Open, FileAccess.Read))
{
data = StreamToBytes(fs);
data = Decompress(data);
}
}
}