文件分割器主要是為了解決實際生活中攜帶大文件的問題,由於存儲介質容量的限制,大的文件往往不能夠一下子拷貝到存儲介質中,這只能通過分割程序把的文件分割多個可攜帶小文件,分步拷貝這些小文件,從而實現攜帶大文件的目的。而合並器的作用則能夠把這些分割的小文件重新合並,恢復原來的文件。.Net FrameWork SDK中提供的許多處理文件的類庫,通過這些類能夠簡捷、靈活的實現對文件的操作。本文的主要內容就是探討一下Visual C#在對文件編程中的一個比較流行的應用--文件分割器和合並器。下面就首先了解一下Visual C#在實現分割、合並器時所使用的.Net FrameWork SDK提供的類庫及其在本文中的使用方法。
一.本文程序設計、調試和運行的環境:
(1).微軟公司視窗2000服務器版。
(2).Visual Studio .Net 2003企業構建版,.Net FrameWork SDK版本號4322。
二.Visual C#實現分割合並程序時使用的類庫及其使用方法:
Visual C#對文件的編程所使用的類庫一般都在.Net FrameWork SDK中的System.IO命名空間中,System.IO命名空間提供了在數據流和文件層次上的存取方法,存取方法一般都提供同步、異步二種模式。Visual C#實現分割合並程序時主要使用的是在數據流層次上的類,主要是:FileStream、BinaryReader和BinaryWriter,這三個類一般都提供了同步、異步模式來存取文件數據流,本文一般采用同步模式,雖然在性能上有所欠缺,但使用起來非常方便,也不容易出錯。
FileStream類對Visual C#實現文件編程是非常重要的類,具體表現在對文件系統中文件的讀、寫操作上。FileStream類為適應各種具體操作,提供了許多構造函數。本文是使用文件路徑對應的字符串和文件打開方式來創建、初始化FileStream實例的。具體語法如下:
public FileStream (
string path ,
FileMode mode
) ;
下面是使用此構造函數創建、初始化FileStream實例的具體代碼:
FileStream SplitFileStream = new FileStream ( "C:\\temp.avi" , FileMode.Open ) ;
表01是FileStream類的常用屬性及其說明:
屬性 說明 CanRead 獲取指示當前流是否支持讀取值。 CanSeek 獲取指示當前流是否支持查找值。 CanWrite 獲取指示當前流是否支持寫入值。 Handle 獲取當前FileStream對象所封裝文件的操作系統文件句柄。 IsAsync 獲取指示FileStream是異步還是同步打開的值。 Length 獲取用字節表示的流長度。 Name 獲取傳遞給構造函數的FileStream的名稱。 Position 獲取或設置此流的當前位置。 表01:FileStream類常用屬性及其說明
FileStream類中最重要的是其中的方法,表02是FileStream類中的常用方法及其說明:
方法 說明 BeginRead 開始異步讀。 BeginWrite 開始異步寫。 Close 關閉文件並釋放與當前文件流關聯的任何資源。 EndRead 等待掛起的異步讀取完成。 EndWrite 結束異步寫入,在I/O操作完成之前一直阻塞。 Flush 清除該流的所有緩沖區,使所有緩沖的數據被寫入基礎設備。 Lock 防止其他進程訪問某個文件的全部或部分。 Read 從流中讀取字節塊並將該數據寫入給定緩沖區中。 ReadByte 從文件中讀取一個字節,並將讀取位置提升一個字節。 Seek 將該流的當前位置設置為給定值。 SetLength 將該流的長度設置為給定值。 Unlock 允許其他進程訪問以前鎖定的某個文件的全部或部分。 Write 使用從緩沖區讀取的數據將字節塊寫入該流。 WriteByte 將一個字節寫入文件流的當前位置。
其中:BeginRead、EndRead和BeginWrite、EndWrite是二對異步方法,其功能相當於Read和Write方法。
BinaryReader類提供了以FileStream類的實例為參數的構造函數,其語法比較簡單,具體如下:
public BinaryReader ( Stream ) ;
下面是通過此構造函數創建、初始化BinaryReader實例的具體代碼,其中SplitFileStream是FileStream實例:
BinaryReader SplitFileReader = new BinaryReader ( SplitFileStream ) ;
BinaryReader類為從當前的數據流中讀取各種讀取數據的方法,掌握了這些方法的使用方法也就掌握了BinaryReader類,表03是BinaryReader類中從數據流中讀取數據的方法及其說明:
方法 說明 Read 從基礎流中讀取字符,並提升流的當前位置。 ReadBoolean 從當前流中讀取Boolean,並使該流的當前位置提升1個字節。 ReadByte 從當前流中讀取下一個字節,並使流的當前位置提升1個字節。 ReadBytes 從當前流中將指定個字節讀入字節數組,並使當前位置提升指定個字節。 ReadChar 從當前流中讀取下一個字符,並根據所使用的 ReadChars 從當前流中讀取指定個字符,以字符數組的形式返回數據,並根據所使用的Encoding和從流中讀取的特定字符,提升當前位置。 ReadDecimal 從當前流中讀取十進制數值,並將該流的當前位置提升十六個字節。 ReadDouble 從當前流中讀取8字節浮點值,並使流的當前位置提升8個字節。 ReadInt16 從當前流中讀取2字節有符號整數,並使流的當前位置提升2個字節。 ReadInt32 從當前流中讀取4字節有符號整數,並使流的當前位置提升4個字節。 ReadInt64 從當前流中讀取8字節有符號整數,並使流的當前位置提升4個字節。 ReadSByte 從此流中讀取一個有符號字節,並使流的當前位置提升1個字節。 ReadSingle 從當前流中讀取4字節浮點值,並使流的當前位置提升4個字節。 ReadString 從當前流中讀取一個字符串。字符串有長度前綴,一次7位地被編碼為整數。 ReadUInt16 使用Little Endian編碼從當前流中讀取2字節無符號整數,並將流的位置提升2個字節。 ReadUInt32 從當前流中讀取4字節無符號整數並使流的當前位置提升4個字節。 ReadUInt64 從當前流中讀取8字節無符號整數並使流的當前位置提升8個字節。 表03:BinaryReader類中從數據流讀取數據方法及其說明
BinaryWriter類也提供了使用以FileStream類的實例為參數的構造函數,其語法和BinaryReader類提供的構造函數非常相似,具體語法如下:
public BinaryWriter ( Stream ) ;
下面是通過此構造函數創建、初始化BinaryWriter實例的具體代碼,其中SplitFileStream是FileStream實例:
BinaryWriter TempWriter = new BinaryWriter (SplitFileStream) ;
BinaryWriter類結構較BinaryReader簡單,表04是BinaryWriter類中的常用方法及其說明:
方法 說明 Close 關閉當前的BinaryWriter和基礎流。 Flush 清理當前編寫器的所有緩沖區,使所有緩沖數據寫入基礎設備。 Seek 設置當前流中的位置。 Write 將值寫入當前流。
表04:BinaryWriter類常用方法及其說明
至此Visual C#實現分割合並程序時所主要使用的類就介紹完了,下面就來介紹Visual C#實現分割文件的解決方法及其具體實現步驟。
三.Visual C#實現分割文件的解決方法及其具體實現步驟:
分割文件其實思路比較簡單,首先要確定要分割成小文件的大小,然後確定大文件以此大小分割後的文件數目,並確定小文件的名稱,最後通過創建的BinaryReader實例從大文件以確定的小文件大小讀取數據,並通過創建BinaryWriter實例向創建的小文件中寫入數據,循環此操作,最終實現把大文件分割成的多個小文件。其具體的實現方法請參考下面實現步驟中的第十步。以下就是Visual C#實現分割大文件程序的具體實現步驟:
1.啟動Visual Studio .Net。
2.選擇菜單【文件】|【新建】|【項目】後,彈出【新建項目】對話框。
3.將【項目類型】設置為【Visual C#項目】。
4.將【模板】設置為【Windows應用程序】。
5.在【名稱】文本框中輸入【文件分割】。
6.在【位置】的文本框中輸入【E:\VS.NET項目】,然後單擊【確定】按鈕,這樣在"E:\VS.NET項目"目錄中就產生了名稱為"文件分割"的文件夾,並在裡面創建了名稱為"文件分割"的項目文件。具體如圖01所示:
圖01:【文件分割】項目之【新建項目】對話框
7.把Visual Studio .Net的當前窗口切換到【Form1.cs(設計)】窗口,並從【工具箱】中的【Windows窗體組件】選項卡中往Form1窗體中拖入下列組件,並執行相應的操作:
一個OpenFileDialog組件,用於選擇要分割的大文件。
一個ProgressBar組件,用以顯示文件分割的進度。
一個ComboBox組件,用以選擇文件分割的大小。
二個TextBox組件,分別用以顯示OpenFileDialog組件選擇後的文件和輸入分割後小文件存放的目錄。
四個Label組件。
二個Button組件,分別用以選擇要分割的大文件和對選定文件進行分割,並在這二個Button組件拖入Form1的設計窗體後,雙擊它們,則系統會在Form1.cs文件分別產生這二個組件的Click事件對應的處理代碼。
8.把Visual Studio .Net的當前窗口切換到【Form1.cs(設計)】窗口,並按照表05所示數值來調整組件的主要屬性:
組件類型 組件名稱 屬性 設置結果 Button button1 FlatStyle Flat button1 Text 執行 button2 FlatStyle Popup button2 Text ... Form Form1 Text 文件分割 Form1 MaximizeBox False Form1 MinimizeBox True Form1 FormBorderStyle FormBorderStyle.FixedSingle ComboBox comboBox1 Items 720 comboBox1 Items 1440 comboBox1 Items 2880 Label label1 Text 請選擇大小: label2 Text 請選擇文件: label3 Text 輸入存放目錄: label4 Text (單位:K) TextBox TextBox1 Text TextBox2 Text
表05:【文件分割】項目中組件主要屬性設定數值表
至此【文件分割】項目的界面設計和功能實現的准備工作就完成了,設計後的界面如圖02所示:
圖02:【文件分割】項目的設計後的界面
9.在【解決方案資源管理器】窗口中,雙擊Form1.cs文件,進入Form1.cs文件的編輯界面。並在Form1.cs文件的開頭,用下列導入命名空間代碼替代系統缺省的導入命名空間代碼。
using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.IO ;
using System.Text ;
using System.Data.OleDb ;
using System.Windows.Forms.Design ;
10.用下列代碼替換Form1.cs中的button2的Click事件對應的處理代碼,下列代碼功能是選定要分割的大文件:
private void button2_Click ( object sender , System.EventArgs e )
{
openFileDialog1.Title = "請選擇要分割的文件名稱" ;
DialogResult drTemp = openFileDialog1.ShowDialog ( ) ;
if ( drTemp == DialogResult.OK && openFileDialog1.FileName != string.Empty )
{
textBox1.Text = openFileDialog1.FileName ;
button1.Enabled = true ;
}
}
11.用下列代碼替換Form1.cs中的button1的Click事件對應的處理代碼,下列代碼功能是按照選擇的文件大小,把選定的文件按照此大小進行分割,並把分割後的文件存放到指定目錄中:
private void button1_Click ( object sender , System.EventArgs e )
{
int iFileSize= Int32.Parse ( comboBox1.Text ) *1024 ;
//根據選擇來設定分割的小文件的大小
if ( Directory.Exists ( textBox2.Text ) )
Directory.Delete ( textBox2.Text ,true ) ;
//如果計算機存在存放分割文件的目錄,則全部刪除此目錄所有文件
else
Directory.CreateDirectory ( textBox2.Text ) ;
//反之則在計算機創建目錄
FileStream SplitFileStream=new FileStream ( textBox1.Text , FileMode.Open ) ;
//以文件的全路對應的字符串和文件打開模式來初始化FileStream文件流實例
BinaryReader SplitFileReader=new BinaryReader ( SplitFileStream ) ;
//以FileStream文件流來初始化BinaryReader文件閱讀器
byte [ ] TempBytes ;
//每次分割讀取的最大數據
int iFileCount = ( int ) ( SplitFileStream.Length / iFileSize ) ;
//小文件總數
progressBar1.Maximum = iFileCount ;
if ( SplitFileStream.Length % iFileSize != 0 ) iFileCount++ ;
string [ ] TempExtra = textBox1.Text.Split ( ’.’ ) ;
/* 循環將大文件分割成多個小文件 */
for ( int i = 1 ; i <= iFileCount ; i++ )
{
string sTempFileName = textBox2.Text + @"\"+i.ToString ( ) .PadLeft ( 4 ,’0’ ) + "." + TempExtra[ TempExtra.Length - 1 ] ; //小文件名
//確定小文件的文件名稱
FileStream TempStream = new FileStream ( sTempFileName , FileMode.OpenOrCreate ) ;
//根據文件名稱和文件打開模式來初始化FileStream文件流實例
BinaryWriter TempWriter = new BinaryWriter ( TempStream ) ;
//以FileStream實例來創建、初始化BinaryWriter書寫器實例
TempBytes = SplitFileReader.ReadBytes ( iFileSize ) ;
//從大文件中讀取指定大小數據
TempWriter.Write ( TempBytes ) ;
//把此數據寫入小文件
TempWriter.Close ( ) ;
//關閉書寫器,形成小文件
TempStream.Close ( ) ;
//關閉文件流
progressBar1.Value = i - 1 ;
}
SplitFileReader.Close ( ) ;
//關閉大文件閱讀器
SplitFileStream.Close ( ) ;
MessageBox.Show ( "分割成功!" ) ;
progressBar1.Value = 0 ;
}
12.至此在上述步驟都正確完成後,【文件分割】項目的全部工作就基本完成了。此時單擊快捷鍵F5運行程序,單擊【…】按鈕選擇要分割的文件,輸入分割文件存放的目錄,並確定分割文件的大小後,單擊【執行】按鈕,則程序就能夠把選定的文件按照選定的大小進行分割,並把分割成的文件存放輸入的目錄中。圖03是【文件分割】項目的運行界面:
圖03:【文件分割】項目的運行界面
Visual C#實現分割文件程序已經全部完成了,下面就來介紹Visual C#把用分割程序分割成的小文件進行合並的解決思路和具體的實現步驟。
四.Visual C#實現合並文件的解決方法及其具體實現步驟:
Visual C#實現合並文件的思路是首先獲得要合並文件所在的目錄,然後確定所在目錄的文件數目,最後通過循環按此目錄文件名稱的順序讀取文件,形成數據流,並使用BinaryWriter在不斷追加,循環結束即合並文件完成。具體的實現方法請參考下面步驟中的第步。以下就是Visual C#實現合並文件的具體實現步驟:
1.啟動Visual Studio .Net。
2.選擇菜單【文件】|【新建】|【項目】後,彈出【新建項目】對話框。
3.將【項目類型】設置為【Visual C#項目】。
4.將【模板】設置為【Windows應用程序】。
5.在【名稱】文本框中輸入【合並程序】。
6.在【位置】的文本框中輸入【E:\VS.NET項目】,然後單擊【確定】按鈕,這樣在"E:\VS.NET項目"目錄中就產生了名稱為"合並程序"的文件夾,並在裡面創建了名稱為"合並程序"的項目文件。具體如圖04所示:
圖04:【合並程序】項目之【新建項目】對話框
7.把Visual Studio .Net的當前窗口切換到【Form1.cs(設計)】窗口,並從【工具箱】中的【Windows窗體組件】選項卡中往Form1窗體中拖入下列組件,並執行相應的操作:
一個OpenFileDialog組件,用於選擇一個合並文件。
一個ProgressBar組件,用以顯示文件合並的進度。
二個TextBox組件,分別用以顯示OpenFileDialog組件選擇後的文件和輸入合並後的大文件的名稱。
二個Label組件。
二個Button組件,分別用以選擇一個合並文件和對選定目錄中的所有文件進行合並,並在這二個Button組件拖入Form1的設計窗體後,雙擊它們,則系統會在Form1.cs文件分別產生這二個組件的Click事件對應的處理代碼。
13.把Visual Studio .Net的當前窗口切換到【Form1.cs(設計)】窗口,並按照表06所示數值來調整組件的主要屬性:
組件類型 組件名稱 屬性 設置結果 Button button1 FlatStyle Flat button1 Text 執行 button2 FlatStyle Popup button2 Text ... Form Form1 Text 合並程序 Form1 MaximizeBox False Form1 MinimizeBox True Form1 FormBorderStyle FormBorderStyle.FixedSingle Label label1 Text 請選擇大小: label2 Text 選擇文件: TextBox TextBox1 Text TextBox2 Text
表06:【文件分割】項目中主要組件屬性設定數值表
至此【合並程序】項目的界面設計和功能實現的准備工作就完成了,設計後的界面如圖05所示:
圖05:【合並程序】項目的設計後的界面
8.在【解決方案資源管理器】窗口中,雙擊Form1.cs文件,進入Form1.cs文件的編輯界面。並在Form1.cs文件的開頭,用下列導入命名空間代碼替代系統缺省的導入命名空間代碼。
using System ;
using System.Drawing ;
using System.Collections ;
using System.ComponentModel ;
using System.Windows.Forms ;
using System.Data ;
using System.IO ;
using System.Text ;
using System.Data.OleDb ;
9.在From1.cs的class代碼區添加下列代碼,下列代碼是定義一個字符串全局變量,用以存放合並文件所在目錄:
public string sDirectoryName = "" ;
//定義一個全局變量,用以存放合並文件所在的目錄
10.用下列代碼替換Form1.cs中的button2的Click事件對應的處理代碼,下列代碼功能是根據文件選擇對話框獲得文件所在的目錄,為後面的文件合並做准備:
private void button2_Click ( object sender , System.EventArgs e )
{
openFileDialog1.Title ="請選擇要合並的第一個文件" ;
System.Windows.Forms.DialogResult drTemp = openFileDialog1.ShowDialog ( ) ;
if ( drTemp == DialogResult.OK && openFileDialog1.FileName != "" )
{
textBox1.Text = openFileDialog1.FileName ;
}
string[ ] path = openFileDialog1.FileName .Split ( @"\".ToCharArray ( ) ) ;
string sTemp = "" ;
int i= 0 ;
for ( i= 0 ; i < path.Length - 1 ; i++ )
{
sTemp = sTemp + path[ i ] + @"\" ;
}
button1.Enabled = true ;
sDirectoryName= sTemp ;
//獲得文件所在目錄
}
11.用下列代碼替換Form1.cs中的button1的Click事件對應的處理代碼,下列代碼功能是合並獲得的文件所在目錄裡面的所有文件,並生成合並文件:
private void button1_Click ( object sender , System.EventArgs e )
{
string[ ] arrFileNames = Directory.GetFiles ( sDirectoryName ) ;
//獲取存放分割後小文件所在目錄所在的所有小文件
int iSumFile = arrFileNames.Length ;
progressBar1.Maximum = iSumFile ;
FileStream AddStream = new FileStream ( textBox2.Text , FileMode.OpenOrCreate ) ;
//以合並後的文件名稱和打開方式來創建、初始化FileStream文件流
BinaryWriter AddWriter = new BinaryWriter ( AddStream ) ;
//以FileStream文件流來初始化BinaryWriter書寫器,此用以合並分割的文件
/*循環合並小文件,並生成合並文件 */
for ( int i = 0 ; i < iSumFile ; i++ )
{
FileStream TempStream = new FileStream ( arrFileNames[ i ] , FileMode.Open ) ;
//以小文件所對應的文件名稱和打開模式來初始化FileStream文件流,起讀取分割作用
BinaryReader TempReader = new BinaryReader ( TempStream ) ;
//用FileStream文件流來初始化BinaryReader文件閱讀器,也起讀取分割文件作用
AddWriter.Write ( TempReader.ReadBytes ( ( int ) TempStream.Length ) ) ;
//讀取分割文件中的數據,並生成合並後文件
TempReader.Close ( ) ;
//關閉BinaryReader文件閱讀器
TempStream.Close ( ) ;
//關閉FileStream文件流
progressBar1.Value = i + 1 ;
//顯示合並進程
}
AddWriter.Close ( ) ;
//關閉BinaryWriter文件書寫器
AddStream.Close ( ) ;
//關閉FileStream文件流
MessageBox.Show ( "成功合並!" ) ;
progressBar1.Value = 0 ;
}
12.至此在上述步驟都正確完成後,【合並程序】項目的全部工作就基本完成了。此時單擊快捷鍵F5運行程序,單擊【…】按鈕選擇分割後文件所在目錄的任一文件,再輸入合並後文件的名稱後,單擊【執行】按鈕,則程序就能夠把合並選擇目錄中的所有文件,並查殺輸入的合並文件。圖06是【合並程序】項目的運行界面:
圖06:【合並程序】項目的運行界面
五.總結:
Visual C#之所以擁有很強的文件處理能力是因為在.Net FrameWork SDK中提供了許多處理文件的類。實現分割大文件程序和合並小文件程序應該是文件編程中比較復雜的應用了,但通過本文的介紹,可見主要使用的是FileStream、BinaryReader和BinaryWriter三個類就基本完成了,並且代碼量也不是很多。其實掌握Visual C#對文件的處理,這三個類是關鍵,也是重點和難點,因為其他處理文件的類要麼和這三個類的用法相似,要麼結構簡單,容易掌握。最後希望本文能夠對您掌握Visual C#,精通Visual C#的文件編程有所幫助。