《第12章文件操作.docx》由会员分享,可在线阅读,更多相关《第12章文件操作.docx(19页珍藏版)》请在课桌文档上搜索。
1、第12章文件操作本章要点 文件和目录的创建、复制、移动、删除 文件的读写操作 异步文件操作本章主要介绍了如何对文件和目录的操作,即我们通常说的输入/输出操作。我们在实际的应用过程中经常会碰到对文件和目录的管理操作。总体来讲,文件和目录的操作主要包括创建、读取,写入、删除、更新等。本章将对以上内容做逐一的介绍和举例,以便初学者较好地理解这些内容。12.1 文件和目录要实现对文件和目录的操作,就必须得到.NET框架中相关类库的支持。在.NET框架的命名空间中就提供了Directory类和File类,通过这些类提供的属性和方法可以完成对文件和目录的创建、移动、浏览、复制、删除等操作。12.1.1 目
2、录操作Directory类提供了创建、查找和移动目录的许多静态方法。因此Directory无须创建类的实例即可调用。DirectoryInfo类与Directory很类似,它表示磁盘上的物理目录,具有可以处理此目录的方法,但必须实例化才能调用。表12.1列出了DireClory类的公共方法。表12.1DireCtOry类的公共方法方法说明CreateDirectory创建指定路径中的所有目录Delete删除指定的目录Exists确定给定路径是否引用磁盘上的现有目录GetCreationTime获取目录的创建日期和时间GetCurrentDirectorjr获取应用程序的当前工作目录GetDir
3、ectories获取指定目录中子目录的名称GetFiIes返回指定目录中的文件的名称GetFileSystemEntries返回指定目录中所有文件和子目录的名称GetLastAccessTime返回上次访问指定文件或目录的日期和时间GetLastWriteTime返回上次写入指定文件或目录的日期和时间GetLogicalDrives检索此计算机上格式为“驱动器号:的逻辑驱动器的名称GetParent检索指定路径的父目录,包括绝对路径和相对路径Move将文件或目录及其内容移到新位置SetCreationTime为指定的文件或目录设置创建日期和时间SetCurrentDirectory将应用程序的
4、当前工作目录设置为指定的目录SetLastAccessTime设置上次访问指定文件或目录的日期和时间SetLastWriteTime设置上次写入目录的日期和时间表12.2列出了DireClOrylnfo类的公共属性。表12.2DgCtOryInfo类的公共属性名称说明Attributes获取或设置当前FiIeSystemInfo的FiIeAliributesCreationTiine获取或设置当前FiIeSystemInfo对象的创建时间Exists获取指示目录是否存在的值Extension获取衣示文件扩展名部分的字符串FullName获取目录或文件的完整目录LastAccessTime获取或
5、设置上次访问当前文件或目录的时间LastWriteTime获取或设置上次写入当前文件或目录的时间Name获取此DireCloryInfO实例的名称Parent获取指定子目录的父目录Rt获取路径的根部分表12.3列出了DirectoryInfo类的公共方法。表12.3DirectOryInfO类的公共方法名称说明Create创建目录CreateSubdirectorjf在指定路径中创建一个或多个子目录。指定路径可以是相对于DirectoryInfo类的此实例的路径Delete从路径中删除DireCtorylnfo及其内容GetDirectories返回当前目录的子目录GetFiles返回当前目录
6、的文件列表MoveTo将DirectoryInfo实例及其内容移动到新路径Refresh刷新对象的状态下面是一个关于目录操作的简单例子。例12.1编写程序,要求判断在指定位置是否存在一个目录,如果存在则删除此目录,否则创建该目录。程序代码:usingSystem;usingic;using/using;using;using;手动加载命名空间namespacecl2_lclassProgramstaticvoidMain(stringargs)/指定目录的路径stringpath=C:CrtDiren;try/判断目录是否存在if(!s(path)/如果不存在则创建目录eDirectory(p
7、ath);1.ine(创建目录成功;)else/如果目录存在,则删除该目录e(path,true);1.ine(删除目录成功;)catch(IOExceptione)1.ine(”处理过程失败:0,fe.ToString();finally分析:上面的例子在控制台应用程序中完成,其中用到了”C:CrtDire”;的表达方式,加个说明后面都是字符串形式,不然就要为“这些进行转义。在中提供了各种输入输出的异常,如对异常IoEXCePtion的捕捉,输出提示信息,便于查找任务失败的原因。12.1.2 Directorylnfo对象的创建要查看目录层次,需要实例化一个DirectoryInfo对象。D
8、irectoryInfo类提供了许多方法,用于典型操作,如复制、移动、重命名、创建和删除目录,可以获得所含文件和目录的名称。如果打算多次重用某个对象,可考虑使用DirectoryInfo的实例方法,而不是Directory类的静态方法,因为并不总是需要安全检查。下面的代码示例演示如何利用DirectoryInfo实例化一个对象目录,并使用其属性获得信息,使用其方法来操作对象。例12.2设计一个程序,将某个目录(含子目录)移到目标文件夹下程序代码:usingSystem;usingic;using;using;using;using/手动加载命名空间namespacecl2_2(classPro
9、gramstaticvoidMain(stringargs)try(/创建一个DireZorY工nfo对象Directoryinfodi=newDirectoryInfo(c:TempDir);/如果不存在的话,建立此目录if(di.Exists=false)di.Create();/在这个新建的目录下建立子目录DirectoryInfodis=di.CreateSubdirectory(SubDirn);/如果目标目录不存在,则建立目录,并将刚才的目录移动至if(s(&c:NewTempDirn)=false)eDirectory(c:NewTempDir);di.MoveTo(0c:New
10、TempDirTempDir);Line(目录已于0移动成功!,di.CreationTime);)catch(IOExceptione)(IAne(移动失败:0,e.ToString();)finally分析:如果试图将c:TempDir移动到Ic:NewTempDir,而c:NewTempDir已经存在,则此方法将引发IOException。因此必须将c:NewTempDirTempDirn作为MoveTo方法的参数。按CW+F5组合键运行后,显示的结果如图12.1所示。SJC:Windowssystem32cmd.exe目录已于2013/8/71?:14:24移动成功!请按磅嬲续.图12
11、.1例12.2的运行结果12.1.3 文件操作FiIe类通常与FileStream类协作完成对文件的创建、删除、复制、移动、打开等操作。与DireCtOry的方法一样,所有的File方法都是静态的,不需要实例化即可以调用File方法。FileInfo和File对象是紧密相关的,与DirectoryInfo一样,FileInfo的所有方法都是实例方法。所以如果只想执行一个操作,那么使用File中的静态方法的效率比使用相应的FileInfo中的实例方法可能更高。所有的File方法都要求当前所操作的文件和目录的路径。表12.4列出了File类公开的成员。表12.4FiIe类公开的成员名称说明Appe
12、ndAllTexl将指定的字符串追加到文件中,如果文件还不存在则创建该文件AppendText创建一个SlreamWriter,它将UTF-8编码文本追加到现有文件Copy将现有文件复制到新文件Create在指定路径中创建文件CreateText创建或打开一个文件,用于写入UTF-8编码的文本Delete删除指定的文件。如果指定的文件不存在,则不引发异常GetAttributes获取在此路径上的文件的FileAttributesGetCreationTime返回指定文件或目录的创建日期和时间GetLastAccessTime返回上次访问指定文件或目录的口期和时间GetLiistWriteTim
13、e返回上次写入指定文件或目录的日期和时间Move将指定文件移到新位置,并提供指定新文件名的选项Open打开指定路径上的FileStreamOpenRead打开现有文件以进行读取OpenText打开现有UTF-8编码文本文件以进行读取OpenWrite打开现有文件以进行写入ReadAHBytes打开一个文件,将文件的内容读入个字符串,然后关闭该文件ReadAlILines打开一个文本文件,将文件的所有行都读入一个字符串数组,然后关闭该文件ReadAlIText打开一个文本文件,将文件的所有行读入到一个字符串中,然后关闭该文件Replace使用其他文件的内容替换指定文件的内容,这一过程将删除原始文
14、件,并创建被替换文件的备份SetAttributes设置指定路径上文件的指定的FileAttributesSetCreationTimc设置创建该文件的日期和时间SetLastAccessTime设置上次访问指定文件的日期和时间SetLastWriteTime设置上次写入指定文件的日期和时间WriieAIIByies创建一个新文件,在其中写入指定的字节数组,然后关闭该文件。如果目标文件已存在,则改写该文件WriteAllLines创建一个新文件,在其中写入指定的字符串,然后关闭文件。如果目标文件已存在,则改写该文件WriteAllText创建一个新文件,在文件中写入内容,然后关闭文件。如果目标
15、文件已存在,则改写该文件表12.5列出了FileInfo类的常用属性。表12.5FileInfo类的常用属性名称说明Attributes获取或设置当前FileSystemInfo的FiIeAttributesCreationTime获取或设置当前FileSystemInfo对象的创建时间Directorjr获取父目录的实例DirectoryName获取表示目录的完整路径的字符串Exists获取指示文件是否存在的值Extension获取表示文件扩展名部分的字符串FullName获取目录或文件的完整目录IsReadOnIy获取或设置确定当前文件是否为只读的值LastAccessTime获取或设置上
16、次访问当前文件或目录的时间LastWriteTime获取或设置上次写入当前文件或目录的时间Length获取当前文件的大小Name获取文件名表12.6列出了FileInfo类的常用方法。表12.6FiIelnfO类的常用方法名称说明AppendText创建一个SlreamWriter,它向FileInfo的此实例表示的文件追加文本CopyTo将现有文件复制到新文件Create创建文件CreateText创建写入新文本文件的StreamWriterDelete永久删除文件MoveTo将指定文件移到新位置,并提供指定新文件名的选项Open用各种读/写访问权限和共享特权打开文件OpenRead创建只读
17、FiIeStreamOpenText创建使用UTF8编码、从现有文本文件中进行读取的StreamReaderOpenWrite创建只写FileStreamRefresh刷新对象的状态Replace使用当前FileInfO对象所描述的文件替换指定文件的内容,这一过程将删除原始文件,并创建被替换文件的备份下面的示例演示了File类中部分成员的用法。该示例通过File类的CreateTeXt()方法创建一个文本,接着向文本写入数据,读取文本内容,使用MoVe()方法进行移动并重命名文件。注意执行程序前需要在C盘新建temp”文件夹。例12.3创建一个程序,利用File类的方法进行文本的创建,数据的读
18、写,以及文本的移动、重命名。程序代码:usingSystem;usingic;using;using;using;using;namespacecl2_3classProgram(staticvoidMain(stringargs)/设定创建文件的路径为C盘根目录,文本文件名称为FiAeKeststringpath=;stringpath2=0c:temp;if(!s(path)(/创建一个文件用于写入UKF-8编码的文本StreamWritersw=eText(path);sw.WriteLine(You);sw.WriteLine(are);sw.WriteLine(beautiful);
19、sw.Dispose();)/打开文件,从里面读出数据StreamReadersr=ext(path);strings=,;/输出文件里的内容,直到文件结束while(s=sr.ReadLine()!null)1.ine(s);)sr.Dispose();try/确保目标路径中没有NeWFileTeSt文件if(s(path2)e(path2);/移动文件(path,path2);1.ine(,O移动至1.fpath,path2);/判断源文件在不在if(S(Path)IAneC,源文件还存在,移动失败!”);)elseIAneC,没有源文件,移动成功!”);catch(Exceptione)
20、IAner移动失败:0fe.ToString();)按Ctrl+F5键运行程序,结果如图12.2所示。SEBC:Windowssystem32crYvd.exeYoua*eBeautifulc:FileTest.txt移动至c三XtenpXHcvFileTest.txt.图12.2例12.3的运行结果在程序运行后,我们可以在C盘根目录下找到新命名的NewFileTest文本文件,可以查看里面内容为:YouarebeautifulMOVeO方法移动范围是整个磁盘,如果尝试通过将一个同名文件移到该目录中来替换文件,将发生IOExceptiono不能使用MOVeo覆盖现有文件。因此此例中要确保目标路
21、径中没有NewFileTest文件。另外程序中的DisposeO是释放对象所占用的资源,如果程序不用了,就可以调用释放。要实现文件重命名只需修改MoVe()中目标文件名参数的文件名即可。此例中是将“FileTesJ修改成rtNewFileTestwo下面的例子用FileInfo的GetFileS()方法得到指定文件夹下的所有文件,用Delete()方法来删除当前目录下的所有文件,并显示文件相关的属性。需要先手工在C盘根目录下创建一个名为Temp的文件夹,在这个新建的文件夹下创建一些文本文件。例12.4编写一个程序,删除所有指定文件夹中的文件。程序代码:usingSystem;usingic;u
22、sing;using/using;using;namespacecl2_4(classProgramstaticvoidMain(stringargs)/创建一个DireCtOry工nfo实例DirectoryInfod=newDirectoryInfo(C:Temp);/创建一个EiAe工cf。数组对象,用于存储指定目录下的文件对象FileInfofis=d.GetFiles();foreach(Fileinfofiinfis)遍历删除各文件fi.Delete();IAne(O文件己删除,文件大小1Bytesffi.Name,fi.Length);分析:GetFiIeS()方法可以得到指定文
23、件夹下的所有文件,将这些得到的文件作为对象依次存储到FileInfo口数组中,利用foreach遍历每个数组元素,将输出每个文件对象的文件名和文件大小的属性信息,并执行Delete()方法来删除这些文件。按CE+F5键运行程序,运行结果如图12.3所示。EEBC:Windowssystem32cmd.exe胃:己.除.区f天、16Bytes已,除这1大,44Bytestest3.xls:文件已删除,藏大小15872Bytes卜est4.pptx文件已射除,文件大429642Bytes请按任意建窿.一图12.3例12.4的运行结果执行完程序再次打开C:Temp文件夹,您将会发现里面己经没有任何文
24、件了。12.2 数据的读取和写入在命名空间中,包含几个用于从流中读写数据的类,各有不同的用途。12.2.1 按文本模式读写StreamReader类和StreamWriter类提供了按文本模式读写数据的方法。表12.7列出了SIreamReader类的常用属性。表12.7StreamReader类的常用属性名称说明BaseStream返回基础流CurrentEncoding获取当前StreamReader对象正在使用的当前字符编码EndOfStream获取一个值,该值表示当前的流位置是否在流的末尾表12.8列出了StreamReader类的常用方法。表12.8StreamReader类的常用方
25、法名称说明Close关闭StreamReader对象和基础流,并释放与读取器关联的所有系统资源DiscardBufferedData允许StreamReader对象丢弃其当前数据Peek返回下一个可用的字符,但不使用它Read读取输入流中的下一个字符或下一组字符ReadBlock从当前流中读取最大COUnt的字符并从index开始将该数据写入bufterReadLine从当前流中读取行字符并将数据作为字符串返回ReadToEnd从流的当前位置到末尾读取流表12.9列出了StreamWriter类的常用属性。表12.9StreamWriter类的常用属性名称说明AutoFlush获取或设置一个值
26、,该值指示SlreamWriIer是否在每次调用之后,将其缓冲区刷新到基础流BaseStream获取与后备存储区连接的基础流Encoding获取将输出写入到其中的EncodingFormatProvider获取控制格式设置的对象NewLine获取或设置由当前TeXtWriter使用的行结束符字符串表12.10列出了StreamWriter类的常用方法。表12.10StreamWriter类的常用方法名称说明Close关闭当前的SlreamWriler对象和基础流Flush清理当前编写器的所有缓冲区,并使所有缓冲数据写入基础流Write写入流WriteLine写入重载参数指定的某些数据,后跟行结
27、束符(从TeXtWriter继承)下面的例子实现了追加文本并读取显示的功能。例12.5使用StreamReader类的方法将数据从文本文件中读出并显示。程序代码:usingSystem;usingic;using;using/using;using;namespacecl2_5(classProgramstaticvoidMain(stringargs)(FileInfofi=newFileInfo(c:);if(!fi.Exists)/创建一个文件并写入StreamMriterswl=fi.CreateText();1.ine(lfHellolf);1.ine(uAndu);1.ine(We
28、lcome);Se();)/在文件中追加内容StreamWritersw2=fi.AppendText();1.ine(This);1.ine(isExtra);1.ine(uTextn);se();/读取并显示文件using(StreamReadersr=fi.OpenText()(strings=,;while(s=sr.ReadLine()!=null)(1.ine(s);按Clrl+F5键运行程序,运行结果如图12.4所示。图12.4例12.5的运行结果下面的示例演示如何使用StreamWriter对象将C盘上的所有文件夹名称写入到一个文件中。此例中的USing标记是用来自动释放资源的
29、,与DiSPOSeo方法相同,只是在执行完using体的语句后会自动执行DiSPOSeo方法虽然微软推荐这种用法,但这样使用USing可能不利于程序的可读性。例12.6使用StreamWriter类,把数据写到文本文件中去。程序代码:usingSystem;usingic;using;using;using;using;namespacecl2_6classProgram(staticvoidMain(stringargs)(/得到C盘下的所有文件夹DirectoryInfocDirs=newDirectoryinfo(,c:).GetDirectories();/将得到的文件夹名写入指定文件
30、内using(StreamWritersw=newStreamWriter(,)foreach(DirectoryInfodirineDirs)sw.VJriteLine();/读取并显示这些文件夹名stringline=;using(StreamReadersr=newStreamReader()(while(line=sr.ReadLine()!=null)(1.ine(line);)12.2.2 按二进制模式读写FileStream类提供了最原始的字节级上的文件读写功能,但我们习惯于对字符串操作,于是StreamWriter和StreamReader类增强了FileStream,它让我们
31、在字符串级别上操作文件,但有的时候我们还是需要在字节级上操作文件,却又不是一个字节一个字节的操作,通常是2个、4个或8个字节这样操作,这便有了BinaryWriter和BinaryReader类,它们可以将一个字符或数字按指定个数字节写入,也可以一次读取指定个数字节转为字符或数字。表12.11列出了BinaryReader类的常用方法。表12.11BinaryReader类的常用方法名称说明Close关闭当前阅读器及基础流PeekChar返回下个可用的字符,并且不提升字节或字符的位置Read从基础流中读取字符,并提升流的当前位置ReadBoolean从当前流中读取Boolean值,并使该流的当
32、前位置提升】个字节ReadByte从当前流中读取卜.一个字节,并使流的当前位置提升1个字节ReadBytes从当前流中将count个字节读入字节数组,并使当前位置提升count个字节ReadChar从当前流中读取下一个字符,并根据所使用的Encoding和从流中读取的特定字符,提升流的当前位置ReadChars从当前流中读取CoUnt个字符,以字符数组的形式返回数据,并根据所使用的Encoding和从流中读取的特定字符,提升当前位置ReadString从当前流中读取一个字符串。字符串有长度前缀,一次7位地被编码为整数表12.12列出了BinaryWriter类的常用方法。表12.12Binar
33、yWriter类的常用方法名称说明Close关闭当前的BinaryWriter和基础流Flush清理当前编写器的所有缓冲区,使所有缓冲数据写入基础设备Seek设置当前流中的位置Write将值写入当前流下面的例子实现了如何向新的空文件流写入数据及从中读取数据。在当前目录中创建了数据文件之后,也就同时创建了相关的BinaryWriter类和BinaryReader类,BinaryWriter类用于向写入字符A-Fo通过BinaryReader类的ReadCharo方法读出指定的内容。例12.7使用BinaryWriter类和BinaryReader类进行二进制文件流的读写。程序代码:usingSy
34、stem;usingic;using;using;using;using;namespacecl2_7classProgram(staticvoidMain(stringargs)FileStreammyFileStream=newFileStream(c:,zeNew);/为文件流创建二进制写入器BinaryWritermyBinaryWriter=newBinaryWriter(myFileStream);/写入数据for(inti=65;i(char)i);)0;0;/创建readermyFileStream=newFileStream(c:,z,);BinaryReaderInyBin
35、aryReader=newBinaryReader(myFileStream);/从BinFile读窥据WhiIe(har()!=-1)(l,0llfhar();0;0;按Ctrl+F5键运行程序,运行结果如图12.5所示。图12.5例12.7的运行结果12.3 异步文件操作以上几小节涉及的都是同步I/O操作,而异步I/O操作在依托计算机高性能的前提下,对程序的执行效率有了较大的提升。在同步I/O操作中,方法将一直处于等待状态,直到I/O操作完成。而在异步I/O操作中,程序的方法仍可以转移去执行其他的操作。在.NETframework4和早期版本中,通过Stream类的BeginReadOEn
36、ciReadOBeginWrite()和EndWriteo方法提供了异步I/O。异步I/O的顺序如下:调用文件的读取方法,然后转向其他与此无关的工作,读取过程将在另一线程中进行。当读取完成时,会有一个回调方法进行通知,然后处理读取的数据,再启动一次读取,然后又回到另一项工作上去。异步操作可以在不必阻止主线程的情况下执行大量占用资源的I/O操作。从.NETFramework4.5开始,I/O类型所包括的异步方法简化了异步操作。异步方法在其名称中包含Async,例如ReadAsyncWriteAsyncCopyToAsync、FlUShASync、ReadLineAsync和ReadToEndAs
37、ynco从VisualStudio2012开始为异步编程提供两个关犍字:(c#)async修饰符,用于指示方案包含一个异步操作。(c#)await运算符,应用于异步方法的结果。有关更多信息,请参见使用Async和Await的异步编程的专用教程。下面的代码演示如何使用复制文件的两FileStream对象异步从一个目录到另一个。请注意Button控件的Click事件处理程序标记async修饰符,因为它调用异步方法。namespaceWpfApplicationpublicpartialclassMainWindow:WindowpublicMainWindow()(InitializeCompon
38、ent();)privateasyncvoidButton_Click(objectsender,RoutedEventArgse)(stringStartDirectory=0,c:Usersexampleuserstart;stringEndDirectory=Qc:Usersexampleuserend;foreach(stringfilenameinrateFiles(StartDirectory)using(FileStreamSourceStream=(filename,)using(FileStreamDestinationStream=e(EndDirectory+ring(n
39、dexf(,W)(awaitoAsync(Destinationstream);12.4 案例实训I1 .案例说明本例主要是涉及文件操作的相关内容,完成文本打开、编辑、保存的操作。2 .编程思路主要使用文件的读取和写入的方法操作文件,利用对话框控件过滤成文本文件,写入时将所有缓冲区数据写入基础流。3 .窗体设计在窗体上添加3个Button按钮、1个TextBox控件、2个GroupBox控件、1个OpenFileDiaIOg控件、1个SaveFileDialog控件。具体的放置如图12.6所示(OPenFileDialog控件和SaveFileDialog不可显示)。,动SS打开和保存文件1丁
40、I百I衣一打开和保存的文件内容I刷她I打开文件I保存文件退出程序图12.6窗体界面4 .程序代码具体的程序代码如下:usingSystem;usingic;usingnentModel;using;usingng;using;using;usingws.Forms;using;namespaceCasel2_lpublicpartialclassForml:FormpublicForml()InitializeComponent();stringmyfi1e=,;privatevoidbuttonl_Click(objectsender,EventArgse)ialog();/打开对话框/定义
41、StreamReader对象实例StreamReadermyread=newStreamReader(amefIt);try(,/stringmys=ine();/读取打开文件的一行while(mys!=null)/如果打开文件不为空,则一行一行读取(=+mys+rn;mys=ine();myfi1e=ame;)catch(Exceptionmye)(读取文件失败!”+ge);提示对话框finally(O;)privatevoidbutton2_Click(objectsender,EventArgse)(if(ialog()=&ame!=,)myfile=ame;/第二个参数为false代表
42、改写内容,不是追加StreamWriterWriter=newStreamWriter(myfileffalse,It);try(foreach(stringlinein)(line+,n,fIt);O”/将缓冲区的数据写入流)catch(Exceptionex)(保存文件失败!+ex.Message);finally0;privatevoidbutton3_Click(objectsender,EventArgse)(0;O;退出程序)5 .运行结果程序的运行结果如图12.7所示。gJB过文存保存文件I退出程序I图127案例的运行结果12.5 小结在般应用中经常会涉及到目录和文件的操作,这时
43、就会遇到文件的读写操作。要在C#语言中进行文件操作,只需要利用NET框架在命名空间中提供的类就可以实现。其中经常用到的类有File、Stream、FileStreamxBinaryReadersBinaryWriter、StreadReadersStreamWriter等。我们通过直接调用或者实例化对象来使用它们的属性和方法。在本章中我们通过实例详细地介绍了如何以File类和Directory类进行目录和文件的操作,以及如何采用StreamReaderaStreamWriter、BinaryReader、BinaryWriter类进行文本模式和二进制模式的文件读写操作。在最后一节,又对文件的异步操作方式做了简单的介绍,需要深入了解的话请参看专项教程。12.6 习题12.8所示,点击显(需要IistView控1 .编写一个程序,在窗体中输入指定目录路径,如图示按钮即可以图标的形式显示此目录中的所有文件名称。件和imageLisl控件)2 .在第1题的基础上添加如图12.9所示的创建按钮,点击创建指定位置的文件夹,再点击显示按钮显示全部文件夹。(需要IiStVieW控件和imageList控件)图12.9案例的运行结果