《C#程序设计基础教程》课件第7章_第1页
《C#程序设计基础教程》课件第7章_第2页
《C#程序设计基础教程》课件第7章_第3页
《C#程序设计基础教程》课件第7章_第4页
《C#程序设计基础教程》课件第7章_第5页
已阅读5页,还剩39页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

第7章文本文件操作7.1文件读取7.2音像店管理4.07.3文件写入7.4我的便签

7.1文件读取

7.1.1文件与流在对文件进行操作的时候,不管什么类型的文件,首先必须以流的形式将其读取到内存中,然后才能够使用相应的对象来完成各种操作。在C#中,我们常用FileStream类来完成这个工作。FileStream类支持对文件系统上的文件进行读取、写入、打开和关闭等操作,它既支持同步操作,也支持异步操作,其语法结构如下:FileStream文件对象操作对象=newFileStream(stringpath,FileModemode[,FileAccessaccess,FileShareshare])参数说明:path:string类型必选参数,需要操作的文件路径。mode:FileMode类型必选参数,打开文件的方式,其只有固定的几个取值,表7-1列出了可取值及其作用。access:FileAccess类型可选参数,用于设置文件访问方式,它只有固定的几个取值,表7-2列出了可取值及其作用。share:FileShare类型可选参数,用于设置文件共享方式,它只有固定的几个取值,表7-3列出了可取值及其作用。通过几个参数的设置,我们就可以轻松地将一个文件读取到内存中:FileStreamfs=newFileStream("c:\\1.txt",FileMode.Append,FileAccess.ReadWrite, FileShare.None);7.1.2文件读取尽管FilmStream对象自己带有相关的读取方法,但是其读出的一般都是字节数组,不利于我们后续的操作,所以在进行文本文件的读取操作时我们一般采用StreamReader类来完成,因为它操作起来更加简单。StreamReader对象是一个建立在文件流基础之上的数据操作对象,它可以以一种特定的编码从字节流中读取字符,一般情况下我们可以使用它读取标准文本文件的各行信息。在创建StreamReader对象时我们需要一个FilmStream对象来帮忙:StreamReadersr=newStreamReader(fs);在创建了StreamReader对象之后我们就可以通过其提供的方法来读取文件中的数据了,常用的读取方法有两个:ReadLine()和ReadToEnd()。ReadLine()方法的作用是从文件中读取一行数据,在使用这个方法的时候一般都需要一个循环结构来读取整个文件的内容:stringstr=null;while((str=sr.ReadLine())!=null){lblDesc.Text+=str;}在上面的代码中需要我们注意的是循环的条件,这样做既可以取值又可以作为循环判断的条件。这种方式适合读取比较大的文件,如果读取小文件则可以使用ReadToEnd():lblDesc.Text=sr.ReadToEnd();尽管操作过程很简单,但是在实际使用过程中,我们发现经常读取出来的是乱码,问题就出在了编码格式上。默认情况下,StreamReader对象采用的是UTF-8的编码格式,而文本文件的默认编码格式则是ANSI。解决的方法就是在创建StreamReader对象时设置一下编码格式:StreamReadersr=newStreamReader(fs,Encoding.Default);Encoding类在这里的作用就是帮助我们以指定的编码格式来读取文件,它可以支持多种不同的编码格式,通过静态属性可以很方便地设置读取格式,表7-4列出了常用的几个属性。当所有的操作都结束之后,一定不要忘记关闭文件流,否则这个文件就无法被其他程序访问:sr.Close();fs.Close();尽管在大多数情况下,关闭FileStream流之后相应的StreamReader对象也会被关闭,但是作为一个好的编程习惯,还是应该在关闭流之前先将读取对象关闭。另外一种常见的使用方式是直接通过StreamReader类来打开文件:StreamReadersr=newStreamReader("c:\\1.txt",Encoding.Default);事实上这两种方式并没有本质上的区别,只不过在第二种方法中文件流变成了一个系统自动创建的隐式对象而已。

7.2音像店管理4.0

7.2.1问题在新版音像店管理程序中,文本文件将作为一种数据存储的手段出现在程序中。当店里有了新的电影或者现在的电影信息发生变化之后,管理员可以很方便地修改文本文件中的内容,这样当用户通过程序查看某部电影的信息时,系统就可以读取这个文件,并且将数据呈现在用户面前,其运行效果如图7-1所示。具体需求如下:(1)影片类型有战争片、科幻片、爱情片、魔幻片和动漫等,可以设定为固定的。(2)选择不同类型的影片后,需要在下面的ListBox中将该类型下的所有电影的名称显示出来。(3)双击一部电影的名称,在窗体右侧显示电影的详细信息。(4)每一部电影包含两个文件:电影封面和电影信息文件。(5)查看的电影超过一部的时候用选项卡的方式呈现。7.2.2需求分析1.选项卡整个程序最显眼的可能就是占了界面大部分的选项卡了,实现这个效果所采用的控件叫TabControl,这是WinForm众多容器类控件中的一个,不过和前面我们接触过的容器控件不同,TabControl控件本身并不能够直接作为其他控件的容器来使用,它是通过TabPage选项卡页控件来工作的,因此在使用TabControl时最重要的就是其TabPages属性,该属性用来设置和管理所有的选项卡页。和ComboBox控件的Items属性相似,TabControl控件的TabPages属性也有自己独立的选项卡页编辑器。点击“添加(A)”按钮就可以添加一个新的选项卡页,每一个选项卡页都可以设置其独立的属性,其中最重要的是Name和Text。Name用来设置选项卡页对象的名称,以tap作为前缀;Text用来设置选项卡页的标题。除了使用编辑器设置选项卡页之外,也可以通过代码的方式来完成这个工作:TabPagetp=newTabPage();tp.Name="tapFilm";tp.Text="超级战舰";tabControl1.TabPages.Add(tp);当然无论采用哪种方式,添加的都只是一个空的选项卡页,如果需要在其上呈现其他控件则还需要更多的操作。同样的,我们也有很多方式来设计选项卡页的内容。如果采用的是编辑器,则可以直接在VS2010中设计界面。如果期望动态地生成界面,则可以通过代码的方式来实现://创建新的选项卡页TabPagetp=newTabPage();tp.Name="tapFilm";tp.Text="超级战舰";//动态添加控件LabellblName=newLabel();lblName.Name="lblName";lblName.Text="姓名:";tp.Controls.Add(lblName);tabShowInfo.TabPages.Add(tp);这种方式可以根据需要动态地生成界面,但是麻烦之处在于需要精确地设定每一个控件的位置和大小。另外一种方式就是将整个窗体嵌入到选项卡页中://创建新窗体和新选项卡frmFilmDetailsfd=newfrmFilmDetails(fileName);TabPagetp=newTabPage();//设置窗体属性fd.TopLevel=false;fd.Parent=tp;fd.Dock=DockStyle.Fill;//添加选项卡tp.Controls.Add(fd);tabShowInfo.TabPages.Add(tp);fd.Show();//刷新和设定选项卡tabShowInfo.Refresh();tabShowInfo.SelectedTab=tp;在上面的代码中,我们首先创建了一个窗体对象和一个选项卡页对象。接下来我们对窗体的几个属性进行设置:TopLevel属性告诉系统我们声明的窗体对象不是一个顶级窗体,这样才能够将其嵌入到其他的容器控件中;Parent属性用来设置窗体对象的父容器,自然这里的父容器就是选项卡页对象了;Dock属性用来设置窗体的停靠方式,我们在这里选择了Fill,也就是填充满父容器。第三步,我们将窗体对象添加到选项卡页中,并且将选项卡页对象添加到TabControl中,然后通过Show()方法打开窗体,这样就完成了窗体的嵌入工作。最后,我们将整个选项卡控件刷新,并设定新添加的选项卡页对象为当前选中的选2.控件联动在我们这一版本的管理程序中,需要实现电影类型、电影名称和电影详细内容之间的联动效果,这需要ComboBox、ListBox和TabControl三个控件的紧密配合。联动的基本实现思路很简单:在ComboBox控件中选择某个电影类型后,在其SelectedIndexChanged事件中向ListBox控件中填充相应的电影名称,在双击ListBox中某个电影后,在其DoubleClick事件中完成在TabControl控件中显示该电影详细信息的工作。根据这个思路,我们需要为所有的电影设置类别这个属性。另外,为了能够显示详细信息,我们还需要为电影设置名称、上映时间、主演和介绍等属性。最好的做法是单独创建一个电影类,将上面提到的内容都定义成其属性,但是这样一来,我们就需要在窗体上声明很多电影类对象或者创建一个电影类的数组。无论采用哪种方式我们的程序中都会产生很多对象,可是我们需要的仅仅是电影的名称而已。因此,在这里我们采用另一种方式去实现,虽然显得很麻烦,但是却能够减少系统的开销,而且让程序变得更加灵活://生成文件名stringpath=Application.StartupPath+"\\Films\\"+(cboType.SelectedIndex+1).ToString()+".txt";StreamReadersr=newStreamReader(path,Encoding.Default);lstFilm.Items.Clear();//读取文件strings=null;while((s=sr.ReadLine())!=null)lstFilm.Items.Add(s);看到这里大家应该就明白了,我们并没有将电影名称放在程序中,而是通过文件读取的方式从外部获得,因此在程序的开始,我们通过ComboBox的SelectedIndex属性来合成文件路径,这里有以下几个地方需要我们特别注意。首先是文件的命名,因为我们是根据控件的选择项来完成操作的,所以我们设定ComboBox控件中每一项的下标加一即为该类型电影的文件名称。这样我们只需要知道ComboBox控件和ListBox控件的选中项下标就可以知道用户所要查看的文件名称了。第二个需要我们关注的是Application.StartupPath,其作用是取得当前可执行文件的路径。在WinForm的文件操作中,如果打开文件的时候只给出文件名而不包含路径,那么该文件必须放在和EXE文件同一路径下或者放在System32目录下,否则就必须给出文件的完整路径。因此,在进行文件操作时我们一般将文件放置在和EXE同一路径或EXE所在目录的子目录下,这样通过Application.StartupPath就可以取得EXE文件所在的目录,然后经过简单的合成就可以获得文件的完整路径了。接下来要完成的就是双击ListBox中的某一项后打开该电影的详细信息,这中间的大部分代码我们在前面选项卡部分已经介绍过了,因此这里只给出其中一部分:stringfileName=(cboType.SelectedIndex+1).ToString()+(lstFilm.SelectedIndex+1).ToString();frmFilmDetailsfd=newfrmFilmDetails(fileName);正如前面我们所介绍的那样,这部分代码并不负责显示电影的详细信息,只是动态地添加一个新的选项卡页,然后将显示电影详细信息的窗体嵌入其中即可,所以我们操作的重点依然是合成文件名,并将其作为参数传递到电影详细信息窗体中即可。3.文件读取与显示当用户在ListBox控件中双击某一个电影后,我们需要将其详细信息呈现出来,当然这个过程还是从获取文件名称开始,采用的方式依然是通过窗体间参数的传递来实现:privatestringfileName=null;publicfrmFilmDetails(stringname){InitializeComponent();this.fileName=name;}这些代码前面已经使用过多次了,这里不再详述。取得文件名后在窗体的Load事件中我们就可以完成具体的操作了://合成路径stringpath=Application.StartupPath+"\\Films\\"+fileName+".txt";stringimage=Application.StartupPath+"\\Films\\"+fileName+".jpg";if(File.Exists(path)){//打开文件FileStreamfs=newFileStream(path,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None);StreamReadersr=newStreamReader(fs,Encoding.Default);//显示信息lblName.Text=sr.ReadLine();lblPubDate.Text=sr.ReadLine();lblType.Text=sr.ReadLine();lblActors.Text=sr.ReadLine();lblDesc.Text=sr.ReadLine();picCover.Image=Image.FromFile(image); //关闭文件sr.Close();fs.Close();}操作过程和上面差不多,首先还是合成文件路径,这里我们需要两个文件的路径,因为一部电影有两个文件:说明文件和封面海报图片。接下来通过FileStream对象和StreamReader对象来打开文件。第三步就是通过调用StreamReader对象的ReadLine()方法来读取并显示文件的内容。最后在操作完成后关闭文件流。7.2.3实现音像店管理4.0新版的音像店管理程序由两个文件组成:frmFilmList.cs:publicpartialclassfrmFilmList:Form{publicfrmFilmList(){InitializeComponent();}privatevoidfrmFilmList_Load(objectsender,EventArgse){cboType.SelectedIndex=0;}privatevoidcboType_SelectedIndexChanged(objectsender,EventArgse){//生成文件名stringpath=Application.StartupPath+"\\Films\\"+(cboType.SelectedIndex+1).ToString()+".txt";StreamReadersr=newStreamReader(path,Encoding.Default);lstFilm.Items.Clear();//读取文件strings=null;while((s=sr.ReadLine())!=null)lstFilm.Items.Add(s);}privatevoidlstFilm_DoubleClick(objectsender,EventArgse){stringfileName=(cboType.SelectedIndex+1).ToString()+(lstFilm.SelectedIndex+1).ToString();//创建新窗体和新选项卡frmFilmDetailsfd=newfrmFilmDetails(fileName);TabPagetp=newTabPage();//设置选项卡信息fd.TopLevel=false;

fd.Parent=tp;fd.Dock=DockStyle.Fill;//显示文件内容tp.Text=lstFilm.SelectedItem.ToString();tp.Controls.Add(fd);//添加选项卡tabShowInfo.TabPages.Add(tp);fd.Show();//刷新和设定选项卡tabShowInfo.Refresh();tabShowInfo.SelectedTab=tp;}}在这个页面上,电影类型已经固定设置在ComboBox控件中,因此在窗体的Load事件中我们设定ComboBox控件的选中项为第一项。在ComboBox控件的SelectedIndexChanged事件中我们通过读取相应的文件来动态地将电影名称添加到ListBox控件中。而在ListBox控件的DoubleClick事件中,我们则通过对几个控件的取值获取到用户所要查看的电影的文件名,并且通过TabControl控件将电影的详细信息呈现在一个新的选项卡页中:frmFilmDetails.cs:publicpartialclassfrmFilmDetails:Form{privatestringfileName=null;publicfrmFilmDetails(stringname){InitializeComponent();this.fileName=name;}privatevoidfrmFilmDetails_Load(objectsender,EventArgse){stringpath=Application.StartupPath+"\\Films\\"+fileName+".txt";stringimage=Application.StartupPath+"\\Films\\"+fileName+".jpg";if(File.Exists(path)){FileStreamfs=newFileStream(path,FileMode.OpenOrCreate,FileAccess.ReadWrite,FileShare.None);StreamReadersr=newStreamReader(fs,Encoding.Default);lblName.Text=sr.ReadLine();lblPubDate.Text=sr.ReadLine();lblType.Text=sr.ReadLine();lblActors.Text=sr.ReadLine();lblDesc.Text=sr.ReadLine();picCover.Image=Image.FromFile(image);sr.Close();fs.Close();}}}这个窗体的任务比较单一,即根据用户所选择的文件读取电影信息并呈现出来,因此几乎所有的代码都写在窗体的Load事件中,具体代码我们在前面已经讲解过了,这里不再详述。

7.3文件写入

写文件和读文件的操作很相似,所使用的对象为StreamWriter,其使用方式和StreamReader也很相似,语法结构如下:StreamWritersw=newStreamWriter(Streamstream);或StreamWritersw=newStreamWriter(stringpath,boolappend,Encodingencoding);参数说明:stream:Stream类型必选参数,要写入的文件流对象。path:string类型必选参数,要写入的完整的文件路径。append:bool类型可选参数,确定是否将数据追加到文件。如果该文件存在,并且append为false,则该文件被覆盖。如果该文件存在,并且append为true,则数据被追加到该文件中。如果该文件不存在,则将创建新文件。encoding:Encoding类型可选参数,要使用的字符编码类型。和StreamReader对象一样,当我们需要向一个文本文件中写入内容的时候,首先也需要创建一个文件流对象,只不过这个流的访问方式必须选择Write或者ReadWrite:FileStreamfs=newFileStream("c:\\1.txt",FileMode.OpenOrCreate,FileAccess.ReadWrite);有了文件流对象后我们就可以创建写入对象:StreamWritersw=newStreamWriter(fs);通过StreamWriter对象的相应方法我们就可以完成对文件的写操作:sw.Write("Hello!");sw.WriteLine("Hello!");这里我们给出了常用的两个方法,它们的作用都是将字符串写入流,区别在于WriteLine()方法在写完后会添加一个换行符,而Write()方法则没有。另外,如果给出的参数为null,那么Write()方法不写入任何内容,而WriteLine()方法会写入一个行结束字符。最后一定不要忘记关闭相关的对象:sw.Flush();sw.Close();fs.Close();我们发现在调用Close()方法之前我们还调用了Flush()方法,该方法的作用是清理当前编写器的所有缓冲区,并使所有缓冲数据写入基础流。因为在进行文件写操作的时候,当我们调用Write()或者WriteLine()方法后,我们所给出的信息实际上并没有真正地写入到磁盘中,而是暂时保存在了系统的缓存中,只有当缓存被装满或者有明确的指令后,这些信息才会真正地写入磁盘文件。因此,如果在结束操作之前没有给出系统写磁盘文件的指令,除非我们运气特别好刚好碰到磁盘存满的情况,否则我们的信息是不会被写入到磁盘文件的。

7.4我的便签

7.4.1问题“我的便签”是一个小程序,能够实现对文本文件的读写操作,其运行效果如图7-3所示。具体要求如下:(1)窗体的工具栏包含7个按钮,分别是:新建、打开、保存、剪切、复制、粘贴和退出。(2)便签的显示仍然采用TabControl控件来实现。7.4.2需求分析1.工具栏工具栏在Windows应用程序中很常见,它一般是由多个按钮、标签等排列组成的,主要是提供一种便捷的方式来快速地执行程序提供的一些常用命令,比使用菜单选择更加方便快捷。在WinForm中,制作工具栏的控件是ToolStrip,该控件通常沿其父窗口顶部“停靠”,但是也可以将它停靠到窗口的任一边上。向Windows窗体中添加一个ToolStrip控件后,窗体顶端会出现一个工具栏,如图7-4所示,单击工具栏上的小箭头,弹出下拉菜单,其中每一项都是可以使用在工具栏上的项类型,常用的有Button按钮、Label标签、ComboBox下拉框等控件,单击某项即可添加到工具栏上。也可以通过ToolStrip控件的Items属性打开“项集合编辑器”来完成工具栏的编辑,如图7-5所示。除了用上述两种方式,我们也可以通过代码来添加按钮:toolStrip1.Items.Add("One");toolStrip1.Items.Add("Two");选中添加到工具栏上的按钮,可以在属性窗口中看到其属性列表。工具栏按钮常用的属性有:Name:用来设置控件的名称,其前缀采用btn。Image:用于设置控件上所呈现出来的图片,一般情况下工具栏都是通过图片的方式来说明其相应的功能。Text:用于设置控件上所呈现的文本内容。DisplayStyle:用于设置控件的呈现方式,可以选择不呈现任何内容(None)、只显示文本(Text)、只显示图片(Image)或者同时显示图片和文字(ImageAndText)。ToolTipText:用于设置当鼠标悬停在控件上时所呈现出来的提示信息。如果是分隔栏则没有任何属性。按钮和分隔栏都没有常用的方法,按钮的常用事件是Click,即被单击时所触发的事件。2.跨窗体控件访问在我们的程序中需要实现几个比较常见的功能:剪切、复制和粘贴。这些功能是不需要我们具体实现的,因为系统的RichTextBox控件已经为我们提供了相应功能实现的方法,难点在于RichTextBox控件在信息呈现的窗体中,而功能菜单却在主窗体上,所以需要解决的问题是如何跨窗体调用控件的方法。仔细分析一下我们会发现,这个问题的焦点其实有两个:如何公开方法以及如何访问控件。因此解决的过程也需要两步。首先,我们必须将RichTextBox控件本身所提供的方法公开出来,默认情况下控件是作为窗体的私有成员存在的,也就是说在窗体的外部无法访问窗体控件,因此才需要进行这个操作。当然实现的过程并不复杂,例如我们可以这样将RichTextBox控件的剪切方法公开出来:publicvoidCut(){txtInfo.Cut();}经过这样的转换,原来私有成员的方法就变成了窗体的公有方法,这样外部用户便可以访问,这就是我们要解决的第二个问题了,即外部用户如何访问。当然最简单的方式就是创建窗体的对象,然后通过对象来访问:frmInfofi=newfrmInfo();fi.Cut();当然这种方式实际上没有什么使用价值,因为我们不可能在用户每次点击菜单的时候都创建一个窗体对象,而且即使这样做了,我们最终所操作的窗体对象也不是原来用户期望操作的窗体对象,所以我们还是要另外想办法。事实上,不论是新建文件还是打开文件,我们都需要创建一个用来显示文件内容的窗体对象,而且这个对象会一直存在,只不过这个窗体对象被我们“放”在了选项卡页中:frmInfofi=newfrmInfo(path);TabPagetp=newTabPage();tp.Controls.Add(fi);因此,只要能够将这个窗体对象从选项卡页中“拿”出来,我们就可以方便地调用其定义的方法了:((frmInfo)tabControl1.SelectedTab.Controls[0]).Cut();上面的代码看起来比较复杂,为了便于理解,我们将其拆开来写:Controlctr=tabControl1.SelectedTab.Controls[0];frmInfofi=(frmInfo)ctr;fi.Cut();事实上这个过程并不复杂,既然我们前面就已经将窗体对象添加到了选项卡页的Controls集合中,那我们就可以通过下标的方式将其提取出来,只不过提取出来的是一个Control类型的对象,因此在第二行代码中我们将其转换为窗体类型,完成这两步后就可以很简单地调用窗体对象的方法了。7.4.3实现“我的便签”在完成了需求分析后,我们就可以具体实现程序了:frmNote.cspublicpartialclassfrmNote:Form{publicfrmNote(){InitializeComponent();}//新建便签privatevoidbtnNew_Click(objectsender,EventArgse){frmInfofi=newfrmInfo(null);TabPagetp=newTabPage();

fi.TopLevel=false;fi.Parent=tp;fi.Dock=DockStyle.Fill;tp.Text="新建便签";tp.Tag=null;tp.Controls.Add(fi);tabControl1.TabPages.Add(tp);tabControl1.SelectedTab=tp;fi.Show();}//打开便签privatevoidbtnOpen_Click(objectsender,EventArgse){

openFileDialog1.Filter="便签文件|*.txt";openFileDialog1.ShowDialog();stringpath=openFileDialog1.FileName;if(File.Exists(path)){frmInfofi=newfrmInfo(path);TabPagetp=newTabPage();fi.TopLevel=false;fi.Parent=tp;fi.Dock=DockStyle.Fill;tp.Text=Path.GetFileName(path);tp.Tag=path;tp.Controls.Add(fi);tabControl1.TabPages.Add(tp);tabControl1.SelectedTab=tp;fi.Show();}}//保存便签privatevoidbtnSave_Click(objectsender,EventArgse){stringpath=null;if(tabControl1.SelectedTab.Tag==null){saveFileDialog1.Filter="便签文件|*.txt";saveFileDialog1.ShowDialog();path=saveFileDialog1.FileName;

}elsepath=tabControl1.SelectedTab.Tag.ToString();((frmInf

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论