文 件分割器主要是为了解决实际生活中携带大文件的问题,由于存储介质容量的限制,大的文件往往不能够一下子拷贝到存储介质中,这只能通过分割程序把的文件分 割多个可携带小文件,分步拷贝这些小文件,从而实现携带大文件的目的。而合并器的作用则能够把这些分割的小文件重新合并,恢复原来的文件。.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#的文件编程有所帮助。