您的位置:首页 > 其它

利用Dataview实现搜索指定目录下的所有文件,以指定的条件排序(可以按文件名升降序,最后修改时间升降序)

2006-04-04 20:42 1056 查看
利用Dataview实现搜索指定目录下的所有文件,以指定的条件排序(可以按文件名升降序,最后修改时间升降序)

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

下面先来了解下C#中操作文件系统的类:
.Net中,有关文件系统操作的类都在System.IO命名空间内,有如下图的类用于浏览文件系统和执行操作.



这些类的作用是:

.System.MarshalByRefObject--.Net类中用于远程操作的基对象类,允许在应用程序域之间调用数据
.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 }
DirectoryInfo dir = new DirectoryInfo(path);
FileSystemInfo[] entryies = dir.GetFileSystemInfos();
FileSystemInfo file;

for (int i=0;i<entryies.Length;i++){
file=entryies[i];
//如果是一个文件
if(file.GetType()==typeof(FileInfo)){
fileList.Add(file.FullName);
}
//如果是一个目录
else if(file.GetType()==typeof(DirectoryInfo)){
SearchFile(file.FullName);
}
}
return fileList;
}

上面的代码用到了一个方法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 }
return true;
}

下面再来增加一点点内容,要求返回以指定后缀名指定大小的文件列表:

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;
}

DirectoryInfo dir = new DirectoryInfo(path);
//指定目录下的文件或者文件夹
FileSystemInfo[] entryies = dir.GetFileSystemInfos();
FileSystemInfo file;

for (int i=0;i<entryies.Length;i++){
//top为负,返回所有找到的文件
if (top>0){
//已达指定数目的文件,则返回
if (fileList.Count>=top){
return fileList;
}
}
file=entryies[i];
//如果是一个文件
if(file.GetType()==typeof(FileInfo)){
//*.*返回所有文件
if (filter=="*.*")
fileList.Add(file.FullName);
else{
//得到文件过滤器数组
string[] filters = filter.Split(new char[]{'|'});
foreach(string flt in filters){
if (file.Name.ToLower().EndsWith(flt.ToLower()))
fileList.Add(file.FullName);
}
}
}
//如果是一个目录
else if(file.GetType()==typeof(DirectoryInfo)){
//递归搜索
SearchFile(file.FullName,filter,top);
}
}
return fileList;
}

有了上面的基础,再来实现一个可排序文件名的方法,这下用到了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);
_dv = new DataView(_ds.Tables[0]);
fileList= new ArrayList();
}

搜索指定目录,填充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();
FileSystemInfo file ;

for (int i=0;i<entryies.Length;i++){
file=entryies[i];
//如果是一个文件
if(file.GetType()==typeof(FileInfo)){
_dr = _dt.NewRow();
if (filter == "*.*"){
_dr[0] = file.FullName.ToString();
_dr[1] = file.LastWriteTime;
//把文件名和最后修改时间加入DataTable
_dt.Rows.Add(_dr);
}
else{
//得到文件过滤器数组
string[] filters = filter.Split(new char[]{'|'});
foreach(string flt in filters){
if(file.Name.ToLower().EndsWith(flt.ToLower())){
_dr[0] = file.FullName.ToString();
_dr[1] = file.LastWriteTime;
//把文件名和最后修改时间加入DataTable
_dt.Rows.Add(_dr);
}
}
}
}
//如果是一个目录,递归调用FileScout方法
else if(file.GetType()==typeof(DirectoryInfo)){
FileScout(file.FullName,filter);
}
}
}

接着定义一个枚举类型,用以方便调用者:

1 /// <summary>
2 /// 排序类型,按指定的条件排序
3 /// </summary>
4 public enum SortBy{
5 /// <summary>
6 /// 按文件名升序
7 /// </summary>
8 FileNameASC,
9 /// <summary>
/// 按文件名降序
/// </summary>
FileNameDESC,
/// <summary>
/// 按最后修改时间升序
/// </summary>
LastUpdatedASC,
/// <summary>
/// 按最后修改时间降序
/// </summary>
LastUpdatedDESC
}

有了上面的方法,接下来就是按条件排序了:

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){
if (!IsDirectory(path)){
return null;
}

//搜索指定目录下的所有文件
FileScout(path,filter);

if (_dt!=null){
switch (sortBy){
case SortBy.FileNameASC:
_dv.Sort = "FileName ASC";
break;
case SortBy.FileNameDESC:
_dv.Sort = "FileName DESC";
break;
case SortBy.LastUpdatedASC:
_dv.Sort = "LastUpdated ASC";
break;
case SortBy.LastUpdatedDESC:
_dv.Sort = "LastUpdated DESC";
break;
default:
_dv.Sort = "LastUpdated ASC";
break;
}
for(int i=0;i<_dv.Count;i++){
//top为负数,返回所有的文件
if(top>0){
if (fileList.Count < top)
fileList.Add(_dv[i]["FileName"].ToString());
else
return fileList; //已找到指定数量的文件
}
else
fileList.Add(_dv[i]["FileName"].ToString());
}
}
else {
return null;
}
return fileList;
}

DataView排序速度挺快的,在我HP4016(1.73G,60G,1024M)上搜索我的音乐目录,按最后修改时间找到20000多个音乐及歌词文件费时11036毫秒,主要是IO的时间吧,第二次搜索排序2700左右.不过内存占用就没法说了..Net打开一个简单的WinForm就10多M了,示例程序在搜索排序期间最多时占内存38M多了.我们的服务器有4G内存,反正从没看到超过2G过.

呵呵..刚学C#,水平有限,本不想放到首页来的,但周围找不到同好,更没有高手指点,所以进展有限,所以想让更多的人看到,帮我指点迷津,谢了.

完整代码和示例可以从这里下载:
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐