在我的应用中,有这样一个案例,测试机为每个已测试的PCB板或者成品生成一份测试报表,为了得知它们的测试详细情况,需要实时捕获各测试条目的结果,所以在服务器上有一Parser分析这些文件,更新到数据库.当然也可以写一个dll给测试程序去调用及更新数据库,但测试机由不同的供应商提供,很难做到这点.
     已知测试机有许多,有许多不同的测试工位,同一时间会产生大量的文件,相临工位有流程控制要求,即上一工位没有Pass记录,下一工位不允许通过.所以Parser要按时间的先后顺序来处理测试报表.查询MSDN帮助文档,并没有实现这个要求相关的类,所以利用DataView的SoryBy方法来实现它,实现的道理很简单,从源目录得到文件名及属性,构造一个DataTable,一列为文件名,另一列为最后修改时间,这样就可以用SortBy方法来处理它了,呵呵,有点取巧.
下面先来了解下C#中操作文件系统的类:
 .Net中,有关文件系统操作的类都在System.IO命名空间内,有如下图的类用于浏览文件系统和执行操作.

这些类的作用是:
.类中用于远程操作的基对象类,允许在应用程序域之间调用数据
 .FileSystemInfo--表示任何文件系统对象的基类
 .FileInfo和File--表示文件系统上的文件
 .DirectoryInfo和Directory--表示文件系统上的文件夹
 .Path--这个类包含的静态成员可以用于处理路径名
其中,Directory和File只包含静态方法,不能被实例化,适于单次操作,DirectoryInfo和FileInfo是有状态的,使用时需要实例化,适用于多次操作的场合.另外,Directory和File每次都要进行安全检查,而DirectoryInfo和FileInfo只有实例化的时候才检查.
类图如下:

好了,有了这些基本的知识,我们先来实现一个简单的方法:得到一个目录下的所有文件
 首先,引入必须的命名空间:
 
using System;
 using System.Data;
 using System.IO;                  //文件操作类所在的命名空间
 using System.Collections;   //ArrayList类所在的命名空间 1         /// <summary>
  2         /// 返回指定目录(包括子目录)的所有的文件列表,找到的文件是系统随机的
  3         /// </summary>
  4         /// <param name="path">有效的目录</param>
  5         /// <returns>ArrayList类型</returns>
  6         public ArrayList SearchFile(string path){
  7             if (!IsDirectory(path)){
  8                 return null;
  9             }
 10             DirectoryInfo dir = new DirectoryInfo(path);
 11             FileSystemInfo[] entryies = dir.GetFileSystemInfos();
 12             FileSystemInfo file;
 13 
 14             for (int i=0;i<entryies.Length;i++){
 15                 file=entryies[i];
 16                 //如果是一个文件
 17                 if(file.GetType()==typeof(FileInfo)){
 18                     fileList.Add(file.FullName);
 19                 }
 20                 //如果是一个目录
 21                 else if(file.GetType()==typeof(DirectoryInfo)){
 22                     SearchFile(file.FullName);
 23                 }
 24             }
 25             return fileList;
 26         }上面的代码用到了一个方法IsDirectory,它只是Directory.Exists()方法的封装,用起来直观一点而已:
1         /// <summary>
  2         /// 检查指定的路径是不是一个有效的目录
  3         /// </summary>
  4         /// <param name="dirPath">需要判断的路径名</param>
  5         /// <returns>是有效的目录,返回true</returns>
  6         public static bool IsDirectory(string dirPath) {
  7             if (!Directory.Exists(dirPath)) {
  8                 return false;
  9             }
 10             return true;
 11         }
 下面再来增加一点点内容,要求返回以指定后缀名指定大小的文件列表:
1         /// <summary>
  2         /// 返回指定目录(包括子目录)的指定数目的文件,未排序,系统随机生成
  3         /// </summary>
  4         /// <param name="path">有效的目录</param>
  5         /// <param name="filter">文件类型(*.*,mp3,txt等),多个格式以|号分隔</param>
  6         /// <param name="top">返回的文件个数,这个参数为负,返回所有找到的文件</param>
  7         public ArrayList SearchFile(string path,string filter,int top){
  8             if (!IsDirectory(path)){
  9                 return null;
 10             }
 11 
 12             DirectoryInfo dir = new DirectoryInfo(path);
 13             //指定目录下的文件或者文件夹
 14             FileSystemInfo[] entryies = dir.GetFileSystemInfos();
 15             FileSystemInfo file;
 16 
 17             for (int i=0;i<entryies.Length;i++){
 18                 //top为负,返回所有找到的文件
 19                 if (top>0){
 20                     //已达指定数目的文件,则返回
 21                     if (fileList.Count>=top){
 22                         return fileList;
 23                     }
 24                 }
 25                 file=entryies[i];
 26                 //如果是一个文件
 27                 if(file.GetType()==typeof(FileInfo)){
 28                     //*.*返回所有文件
 29                     if (filter=="*.*")
 30                         fileList.Add(file.FullName);
 31                     else{
 32                         //得到文件过滤器数组
 33                         string[] filters = filter.Split(new char[]{'|'});
 34                         foreach(string flt in filters){
 35                             if (.ToLower().EndsWith(flt.ToLower()))
 36                                 fileList.Add(file.FullName);
 37                         }
 38                     }
 39                 }
 40                 //如果是一个目录
 41                 else if(file.GetType()==typeof(DirectoryInfo)){
 42                     //递归搜索
 43                     SearchFile(file.FullName,filter,top);
 44                 }
 45             }
 46             return fileList;
 47         }
 有了上面的基础,再来实现一个可排序文件名的方法,这下用到了System.Data命名空间的DataTable等,本来原先自已写了一个快速排序和一个冒泡排序,可与DataView的排序速度差了一个数量级,有人说Windows程序员永远不要认为自已做得比M$好,这话说得不错.废话少说,下面先来初始化一个DataTable,构造一个两列的DataTable,一个是文件名,另一个最后修改时间:
1         /// <summary>
  2         /// 初始化
  3         /// </summary>
  4         private void Init(){
  5             _dt = new DataTable("FilesTable");
  6             _dt.Columns.Add("FileName", typeof(string));
  7             _dt.Columns.Add("LastUpdated", typeof(DateTime));
  8             _ds = new DataSet("FileList");
  9             _ds.Tables.Add(_dt);
 10             _dv = new DataView(_ds.Tables[0]);
 11             fileList= new ArrayList();
 12         }
 搜索指定目录,填充DataTable,实现方法和上面的SearchFile方法差不多,只不过是用DataTable代替ArrayList而已:
1         /// <summary>
  2         /// 得到指定目录下所有指定文件格式的文件,包括子目录
  3         /// </summary>
  4         /// <param name="path">有效的目录</param>
  5         /// <param name="filter">文件类型(*.*,mp3,txt等),*.*返回所有文件,
  6         /// 多种格式以|字符分隔,如mp3|txt|log,不区分大小写</param>
  7         private void FileScout(string path,string filter){
  8             DirectoryInfo dir = new DirectoryInfo(path);
  9             FileSystemInfo[] entryies = dir.GetFileSystemInfos();
 10             FileSystemInfo file ;
 11 
 12             for (int i=0;i<entryies.Length;i++){
 13                 file=entryies[i];
 14                 //如果是一个文件
 15                 if(file.GetType()==typeof(FileInfo)){
 16                     _dr = _dt.NewRow();
 17                     if (filter == "*.*"){
 18                         _dr[0] = file.FullName.ToString();
 19                         _dr[1] = file.LastWriteTime;
 20                         //把文件名和最后修改时间加入DataTable
 21                         _dt.Rows.Add(_dr);
 22                     }
 23                     else{
 24                         //得到文件过滤器数组
 25                         string[] filters = filter.Split(new char[]{'|'});
 26                         foreach(string flt in filters){
 27                             if(.ToLower().EndsWith(flt.ToLower())){
 28                                 _dr[0] = file.FullName.ToString();
 29                                 _dr[1] = file.LastWriteTime;
 30                                 //把文件名和最后修改时间加入DataTable
 31                                 _dt.Rows.Add(_dr);
 32                             }
 33                         }
 34                     }
 35                 }
 36                 //如果是一个目录,递归调用FileScout方法
 37                 else if(file.GetType()==typeof(DirectoryInfo)){
 38                     FileScout(file.FullName,filter);
 39                 }
 40             }
 41         }
 42
 接着定义一个枚举类型,用以方便调用者:
1         /// <summary>
  2         /// 排序类型,按指定的条件排序
  3         /// </summary>
  4         public enum SortBy{
  5             /// <summary>
  6             /// 按文件名升序
  7             /// </summary>
  8             FileNameASC,
  9             /// <summary>
 10             /// 按文件名降序
 11             /// </summary>
 12             FileNameDESC,
 13             /// <summary>
 14             /// 按最后修改时间升序
 15             /// </summary>
 16             LastUpdatedASC,
 17             /// <summary>
 18             /// 按最后修改时间降序
 19             /// </summary>
 20             LastUpdatedDESC
 21         }
 有了上面的方法,接下来就是按条件排序了:
1         /// <summary>
  2         /// 返回一个指定目录指定大小已排序的文件列表,如果top参数小于0,返回所有文件
  3         /// </summary>
  4         /// <param name="path">有效的目录名</param>
  5         /// <param name="filter">文件类型(*.*,mp3,txt等),*.*返回所有文件,
  6         /// 多种格式以|字符分隔,如mp3|txt|log,不区分大小写</param>
  7         /// <param name="sortBy">按条件排序,文件名升降序,修改时间升降序</param>
  8         /// <param name="top" >返回指定记录大小</param>
  9         public ArrayList FileSorter(string path,string filter,FileSearcher.SortBy sortBy,int top){
 10             if (!IsDirectory(path)){
 11                 return null;
 12             }
 13 
 14             //搜索指定目录下的所有文件
 15             FileScout(path,filter);
 16             
 17             if (_dt!=null){
 18                 switch (sortBy){
 19                     case SortBy.FileNameASC:
 20                         _dv.Sort = "FileName ASC";
 21                         break;
 22                     case SortBy.FileNameDESC:
 23                         _dv.Sort = "FileName DESC";
 24                         break;
 25                     case SortBy.LastUpdatedASC:
 26                         _dv.Sort = "LastUpdated ASC";
 27                         break;
 28                     case SortBy.LastUpdatedDESC:
 29                         _dv.Sort = "LastUpdated DESC";
 30                         break;
 31                     default:
 32                         _dv.Sort = "LastUpdated ASC";
 33                         break;
 34                 }
 35                 for(int i=0;i<_dv.Count;i++){
 36                     //top为负数,返回所有的文件
 37                     if(top>0){
 38                         if (fileList.Count < top)
 39                             fileList.Add(_dv[i]["FileName"].ToString());
 40                         else
 41                             return fileList;    //已找到指定数量的文件
 42                     }
 43                     else
 44                         fileList.Add(_dv[i]["FileName"].ToString());
 45                 }
 46             }
 47             else {
 48                 return null;
 49             }
 50             return fileList;
 51         }
 DataView排序速度挺快的,在我HP4016(1.73G,60G,1024M)上搜索我的音乐目录,按最后修改时间找到20000多个音乐及歌词文件费时11036毫秒,主要是IO的时间吧,第二次搜索排序2700左右.不过内存占用就没法说了..Net打开一个简单的WinForm就10多M了,示例程序在搜索排序期间最多时占内存38M多了.我们的服务器有4G内存,反正从没看到超过2G过.
呵呵..刚学C#,水平有限,本不想放到首页来的,但周围找不到同好,更没有高手指点,所以进展有限,所以想让更多的人看到,帮我指点迷津,谢了.
  
 
 
                     
            
        













 
                    

 
                 
                    