首 页 网络编程
网页制作 图形图象 操作系统 冲浪宝典
软件教学 认证考试

网络安全 网络办公 行业资讯 评测对比
您当前位置:站长天空 -> 冲浪宝典-> 联络聊天
c#使用win32api来遍历文件和目录_c#应用
作者:网友供稿 点击:0
推荐
西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!可在线rar解压,自动数据恢复设置虚拟目录等.免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金
站内搜索
文章页数:[1] 

我们有时需要遍历某个目录下的文件和子目录,可以使用System.IO.DirectoryInfo.GetDirectories或GetFiles来获得目录下的所有的文件和子目录,当这个目录下的内容比较多时,这个操作就比较耗时间,有时我们仅仅需要知道某个目录下是否有子目录,这样的操作显然是浪费时间的。此时我们很容易想到三个Win32API函数 FindFirstFile,FindNextFile和FindClose。这三个API搭配使用就能遍历文件和子目录了,而且可以遍历的时候随时中止,避免无谓的操作。

C#中可以使用foreach来遍历某个序列,遍历使用的对象必须实现 System.Collections.IEnumeable接口,而内部调用的遍历器则必须实现System.Collections.IEnumerator , 为了使用方便,我们在使用FindFirstFile等API函数时封装为 IEnumerator,而且实际上是有条件封装的。

这里很多人就会提到C#调用API的执行效率问题,认为应当用C,C++调用API才是正道,使用C#调用则有些鸡肋。但在我个人编程经历中,也有不少调用API的,经验发现其实效率问题不大,可以省略。我只是做常规的运行在PC机上面的软件,CPU通常超过1GHZ,而且无需考虑高实时性和高效率。若过于考虑效率问题会加大软件开发消耗。从工程开发管理方面看是不合理的。我应当解决比较突出的效率问题,不突出的影响不大的效率问题有时间才去解决。使用C#封装Win32API必然会降低执行效率,但是封装后使用方便快捷,综合考虑认为这是正确的。

这里说一下“技术镀金”这个问题,所谓技术镀金就是开发人员在项目软件开发中过于追求技术的完美性,试图在技术上镀上一层完美的金壳,导致软件开发工作量加大,项目时间拉长,有可能导致项目的失败。我吃过“技术镀金”的苦头,现在我内心是追求完美的,但实际开发时经常有意压制追求完美的心思。

现在继续探讨封装大计,本次封装重点在于实现IEnumerator,而IEnumeable只是IEnumerator的一个包装。IEnumerator实现方法 Reset , MoveNext 和属性 Current,Reset方法用于重新设置遍历器,MoveNext用于查找下一个文件或目录,而Current返回当前文件或目录。

这个遍历器还得注意FindClose的调用,必须在遍历完毕没有找到文件或子目录后调用,若不调用该API函数则会造成内存泄漏。

根据上述设计,我写出如下代码,这段代码功能单一,希望有人能用得上

 

/// <summary>
/// 文件或目录遍历器,本类型为 FileDirectoryEnumerator 的一个包装
/// </summary>
/// <remarks>
///
/// 编写 袁永福 ( http://www.xdesigner.cn )2006-12-8
///
/// 以下代码演示使用这个文件目录遍历器
///
/// FileDirectoryEnumerable e = new FileDirectoryEnumerable();
/// e.SearchPath = @"c:\";
/// e.ReturnStringType = true ;
/// e.SearchPattern = "*.exe";
/// e.SearchDirectory = false ;
/// e.SearchFile = true;
/// foreach (object name in e)
/// {
///     System.Console.WriteLine(name);
/// }
/// System.Console.ReadLine();
///
///</remarks>
public class FileDirectoryEnumerable : System.Collections.IEnumerable
{
    private bool bolReturnStringType = true;
    /// <summary>
    /// 是否以字符串方式返回查询结果,若返回true则当前对象返回为字符串,
    /// 否则返回 System.IO.FileInfo或System.IO.DirectoryInfo类型
    /// </summary>
    public bool ReturnStringType
    {
        get { return bolReturnStringType; }
        set { bolReturnStringType = value; }
    }

    private string strSearchPattern = "*";
    /// <summary>
    /// 文件或目录名的通配符
    /// </summary>
    public string SearchPattern
    {
        get { return strSearchPattern; }
        set { strSearchPattern = value; }
    }
    private string strSearchPath = null;
    /// <summary>
    /// 搜索路径,必须为绝对路径
    /// </summary>
    public string SearchPath
    {
        get { return strSearchPath; }
        set { strSearchPath = value; }
    }

    private bool bolSearchForFile = true;
    /// <summary>
    /// 是否查找文件
    /// </summary>
    public bool SearchForFile
    {
        get { return bolSearchForFile; }
        set { bolSearchForFile = value; }
    }
    private bool bolSearchForDirectory = true;
    /// <summary>
    /// 是否查找子目录
    /// </summary>
    public bool SearchForDirectory
    {
        get { return bolSearchForDirectory; }
        set { bolSearchForDirectory = value; }
    }

    private bool bolThrowIOException = true;
    /// <summary>
    /// 发生IO错误时是否抛出异常
    /// </summary>
    public bool ThrowIOException
    {
        get { return this.bolThrowIOException; }
        set { this.bolThrowIOException = value; }
    }
    /// <summary>
    /// 返回内置的文件和目录遍历器
    /// </summary>
    /// <returns>遍历器对象</returns>
    public System.Collections.IEnumerator GetEnumerator()
    {
        FileDirectoryEnumerator e = new FileDirectoryEnumerator();
        e.ReturnStringType = this.bolReturnStringType;
        e.SearchForDirectory = this.bolSearchForDirectory;
        e.SearchForFile = this.bolSearchForFile;
        e.SearchPath = this.strSearchPath;
        e.SearchPattern = this.strSearchPattern;
        e.ThrowIOException = this.bolThrowIOException;
        myList.Add(e);
        return e;
    }
    /// <summary>
    /// 关闭对象
    /// </summary>
    public void Close()
    {
        foreach (FileDirectoryEnumerator e in myList)
        {
            e.Close();
        }
        myList.Clear();
    }

    private System.Collections.ArrayList myList = new System.Collections.ArrayList();

}//public class FileDirectoryEnumerable : System.Collections.IEnumerable

/// <summary>
/// 文件和目录的遍历器
/// </summary>
/// <remarks>本对象为Win32API函数 FindFirstFile , FindNextFile
/// 和 FindClose 的一个包装
///
/// 以下代码演示使用了 FileDirectoryEnumerator
///
/// FileDirectoryEnumerator e = new FileDirectoryEnumerator();
/// e.SearchPath = @"c:\";
/// e.Reset();
/// e.ReturnStringType = true ;
/// while (e.MoveNext())
/// {
///     System.Console.WriteLine
///         ( e.LastAccessTime.ToString("yyyy-MM-dd HH:mm:ss")
///         + "   " + e.FileLength + "  \t" + e.Name );
/// }
/// e.Close();
/// System.Console.ReadLine();
///
/// 编写 袁永福 ( http://www.xdesigner.cn )2006-12-8</remarks>
public class FileDirectoryEnumerator : System.Collections.IEnumerator
{
   
    #region 表示对象当前状态的数据和属性 **********************************

    /// <summary>
    /// 当前对象
    /// </summary>
    private object objCurrentObject = null;

    private bool bolIsEmpty = false;
    /// <summary>
    /// 该目录为空
    /// </summary>
    public bool IsEmpty
    {
        get { return bolIsEmpty; }
    }
    private int intSearchedCount = 0;
    /// <summary>
    /// 已找到的对象的个数
    /// </summary>
    public int SearchedCount
    {
        get { return intSearchedCount; }
    }
    private bool bolIsFile = true;
    /// <summary>
    /// 当前对象是否为文件,若为true则当前对象为文件,否则为目录
    /// </summary>
    public bool IsFile
    {
        get { return bolIsFile; }
    }
    private int intLastErrorCode = 0;
    /// <summary>
    /// 最后一次操作的Win32错误代码
    /// </summary>
    public int LastErrorCode
    {
        get { return intLastErrorCode; }
    }
    /// <summary>
    /// 当前对象的名称
    /// </summary>
    public string Name
    {
        get
        {
            if (this.objCurrentObject != null)
            {
                if (objCurrentObject is string)
                    return (string)this.objCurrentObject;
                else
                    return ((System.IO.FileSystemInfo)this.objCurrentObject).Name;
            }
            return null;
        }
    }
    /// <summary>
    /// 当前对象属性
    /// </summary>
    public System.IO.FileAttributes Attributes
    {
        get { return (System.IO.FileAttributes)myData.dwFileAttributes; }
    }
    /// <summary>
    /// 当前对象创建时间
    /// </summary>
    public System.DateTime CreationTime
    {
        get
        {
            long time = ToLong(myData.ftCreationTime_dwHighDateTime, myData.ftCreationTime_dwLowDateTime);
            System.DateTime dtm = System.DateTime.FromFileTimeUtc(time);
            return dtm.ToLocalTime();
        }
    }
    /// <summary>
    /// 当前对象最后访问时间
    /// </summary>
    public System.DateTime LastAccessTime
    {
        get
        {
            long time = ToLong(myData.ftLastAccessTime_dwHighDateTime, myData.ftLastAccessTime_dwLowDateTime);
            System.DateTime dtm = System.DateTime.FromFileTimeUtc(time);
            return dtm.ToLocalTime();
        }
    }
    /// <summary>
    /// 当前对象最后保存时间
    /// </summary>
    public System.DateTime LastWriteTime
    {
        get
        {
            long time = ToLong(myData.ftLastWriteTime_dwHighDateTime, myData.ftLastWriteTime_dwLowDateTime);
            System.DateTime dtm = System.DateTime.FromFileTimeUtc(time);
            return dtm.ToLocalTime();
        }
    }
    /// <summary>
    /// 当前文件长度,若为当前对象为文件则返回文件长度,若当前对象为目录则返回0
    /// </summary>
    public long FileLength
    {
        get
        {
            if (this.bolIsFile)
                return ToLong(myData.nFileSizeHigh, myData.nFileSizeLow);
            else
                return 0;
        }
    }

    #endregion

    #region 控制对象特性的一些属性 ****************************************

    private bool bolThrowIOException = true;
    /// <summary>
    /// 发生IO错误时是否抛出异常
    /// </summary>
    public bool ThrowIOException
    {
        get { return this.bolThrowIOException; }
        set { this.bolThrowIOException = value; }
    }
    private bool bolReturnStringType = true;
    /// <summary>
    /// 是否以字符串方式返回查询结果,若返回true则当前对象返回为字符串,
    /// 否则返回 System.IO.FileInfo或System.IO.DirectoryInfo类型
    /// </summary>
    public bool ReturnStringType
    {
        get { return bolReturnStringType; }
        set { bolReturnStringType = value; }
    }
   
    private string strSearchPattern = "*";
    /// <summary>
    /// 要匹配的文件或目录名,支持通配符
    /// </summary>
    public string SearchPattern
    {
        get { return strSearchPattern; }
        set { strSearchPattern = value; }
    }
    private string strSearchPath = null;
    /// <summary>
    /// 搜索的父目录,必须为绝对路径,不得有通配符,该目录必须存在
    /// </summary>
    public string SearchPath
    {
        get { return strSearchPath; }
        set { strSearchPath = value; }
    }

    private bool bolSearchForFile = true;
    /// <summary>
    /// 是否查找文件
    /// </summary>
    public bool SearchForFile
    {
        get { return bolSearchForFile; }
        set { bolSearchForFile = value; }
    }
    private bool bolSearchForDirectory = true;
    /// <summary>
    /// 是否查找子目录
    /// </summary>
    public bool SearchForDirectory
    {
        get { return bolSearchForDirectory; }
        set { bolSearchForDirectory = value; }
    }

    #endregion

    /// <summary>
    /// 关闭对象,停止搜索
    /// </summary>
    public void Close()
    {
        this.CloseHandler();
    }

    #region IEnumerator 成员 **********************************************

    /// <summary>
    /// 返回当前对象
    /// </summary>
    public object Current
    {
        get { return objCurrentObject ; }
    }
    /// <summary>
    /// 找到下一个文件或目录
    /// </summary>
    /// <returns>操作是否成功</returns>
    public bool MoveNext()
    {
        bool success = false;
        while (true)
        {
            if (this.bolStartSearchFlag)
                success = this.SearchNext();
            else
                success = this.StartSearch();
            if (success)
            {
                if (this.UpdateCurrentObject())
                    return true;
            }
            else
            {
                this.objCurrentObject = null;
                return false;
            }
        }
    }

    /// <summary>
    /// 重新设置对象
    /// </summary>
    public void Reset()
    {
        if (this.strSearchPath == null)
            throw new System.ArgumentNullException("SearchPath can not null");
        if (this.strSearchPattern == null || this.strSearchPattern.Length == 0)
            this.strSearchPattern = "*";

        this.intSearchedCount = 0;
        this.objCurrentObject = null;
        this.CloseHandler();
        this.bolStartSearchFlag = false;
        this.bolIsEmpty = false;
        this.intLastErrorCode = 0;
    }

    #endregion

    #region 声明WIN32API函数以及结构 **************************************

    [Serializable,
    System.Runtime.InteropServices.StructLayout
        (System.Runtime.InteropServices.LayoutKind.Sequential,
        CharSet = System.Runtime.InteropServices.CharSet.Auto
        ),
    System.Runtime.InteropServices.BestFitMapping(false)]
    private struct WIN32_FIND_DATA
    {
        public int dwFileAttributes;
        public int ftCreationTime_dwLowDateTime;
        public int ftCreationTime_dwHighDateTime;
        public int ftLastAccessTime_dwLowDateTime;
        public int ftLastAccessTime_dwHighDateTime;
        public int ftLastWriteTime_dwLowDateTime;
        public int ftLastWriteTime_dwHighDateTime;
        public int nFileSizeHigh;
        public int nFileSizeLow;
        public int dwReserved0;
        public int dwReserved1;
        [System.Runtime.InteropServices.MarshalAs
            (System.Runtime.InteropServices.UnmanagedType.ByValTStr,
            SizeConst = 260)]
        public string cFileName;
        [System.Runtime.InteropServices.MarshalAs
            (System.Runtime.InteropServices.UnmanagedType.ByValTStr,
            SizeConst = 14)]
        public string cAlternateFileName;
    }

    [System.Runtime.InteropServices.DllImport
        ("kernel32.dll",
        CharSet = System.Runtime.InteropServices.CharSet.Auto,
        SetLastError = true)]
    private static extern IntPtr FindFirstFile(string pFileName, ref WIN32_FIND_DATA pFindFileData);

    [System.Runtime.InteropServices.DllImport
        ("kernel32.dll",
       CharSet = System.Runtime.InteropServices.CharSet.Auto,
        SetLastError = true)]
    private static extern bool FindNextFile(IntPtr hndFindFile, ref WIN32_FIND_DATA lpFindFileData);

    [System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
    private static extern bool FindClose(IntPtr hndFindFile);

    private static long ToLong( int height , int low)
    {
        long v = ( uint ) height ;
        v = v << 0x20;
        v = v | ( ( uint )low );
        return v;
    }

    private static void WinIOError(int errorCode, string str)
    {
        switch (errorCode)
        {
            case 80:
                throw new System.IO.IOException("IO_FileExists :" + str);
            case 0x57:
                throw new System.IO.IOException("IOError:" + MakeHRFromErrorCode(errorCode));
            case 0xce:
                throw new System.IO.PathTooLongException("PathTooLong:" + str );
            case 2:
                throw new System.IO.FileNotFoundException("FileNotFound:" + str);
            case 3:
                throw new System.IO.DirectoryNotFoundException("PathNotFound:" + str);
            case 5:
                throw new UnauthorizedAccessException("UnauthorizedAccess:" + str);
            case 0x20:
                throw new System.IO.IOException("IO_SharingViolation:" + str);
        }
        throw new System.IO.IOException("IOError:" + MakeHRFromErrorCode(errorCode));
    }

    private static int MakeHRFromErrorCode(int errorCode)
    {
        return (-2147024896 | errorCode);
    }

    #endregion

    #region 内部代码群 ****************************************************

    private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
    /// <summary>
    /// 查找处理的底层句柄
    /// </summary>
    private System.IntPtr intSearchHandler = INVALID_HANDLE_VALUE;

    private WIN32_FIND_DATA myData = new WIN32_FIND_DATA();
    /// <summary>
    /// 开始搜索标志
    /// </summary>
    private bool bolStartSearchFlag = false;
    /// <summary>
    /// 关闭内部句柄
    /// </summary>
    private void CloseHandler()
    {
        if (this.intSearchHandler != INVALID_HANDLE_VALUE)
        {
            FindClose(this.intSearchHandler);
            this.intSearchHandler = INVALID_HANDLE_VALUE;
        }
    }
    /// <summary>
    /// 开始搜索
    /// </summary>
    /// <returns>操作是否成功</returns>
    private bool StartSearch()
    {
        bolStartSearchFlag = true;
        bolIsEmpty = false;
        objCurrentObject = null;
        intLastErrorCode = 0;

        string strPath = System.IO.Path.Combine(strSearchPath, this.strSearchPattern);
        this.CloseHandler();
        intSearchHandler = FindFirstFile(strPath, ref myData);
        if (intSearchHandler == INVALID_HANDLE_VALUE)
        {
            intLastErrorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            if (intLastErrorCode == 2)
            {
                bolIsEmpty = true;
                return false;
            }
            if( this.bolThrowIOException )
                WinIOError( intLastErrorCode , strSearchPath);
            else
                return false;
        }
        return true;
    }
    /// <summary>
    /// 搜索下一个
    /// </summary>
    /// <returns>操作是否成功</returns>
    private bool SearchNext()
    {
        if (bolStartSearchFlag == false)
            return false;
        if (bolIsEmpty)
            return false;
        if (intSearchHandler == INVALID_HANDLE_VALUE)
            return false;
        intLastErrorCode = 0 ;
        if (FindNextFile(intSearchHandler, ref myData) == false)
        {
            intLastErrorCode = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            this.CloseHandler();
            if (intLastErrorCode != 0 && intLastErrorCode != 0x12)
            {
                if (this.bolThrowIOException)
                    WinIOError(intLastErrorCode , strSearchPath);
                else
                    return false;
            }
            return false;
        }
        return true;
    }//private bool SearchNext()

    /// <summary>
    /// 更新当前对象
    /// </summary>
    /// <returns>操作是否成功</returns>
    private bool UpdateCurrentObject()
    {
        if (intSearchHandler == INVALID_HANDLE_VALUE)
            return false;
        bool Result = false;
        this.objCurrentObject = null;
        if ((myData.dwFileAttributes & 0x10) == 0)
        {
            // 当前对象为文件
            this.bolIsFile = true;
            if (this.bolSearchForFile)
                Result = true;
        }
        else
        {
            // 当前对象为目录
            this.bolIsFile = false;
            if (this.bolSearchForDirectory)
            {
                if (myData.cFileName == "." || myData.cFileName == "..")
                    Result = false;
                else
                    Result = true;
            }
        }
        if (Result)
        {
            if (this.bolReturnStringType)
                this.objCurrentObject = myData.cFileName;
            else
            {
                string p = System.IO.Path.Combine(this.strSearchPath, myData.cFileName);
                if (this.bolIsFile)
                {
                    this.objCurrentObject = new System.IO.FileInfo(p);
                }
                else
                {
                    this.objCurrentObject = new System.IO.DirectoryInfo(p);
                }
            }
            this.intSearchedCount++;
        }
        return Result;
    }//private bool UpdateCurrentObject()

    #endregion

}//public class FileDirectoryEnumerator : System.Collections.IEnumerator

http://www.cnblogs.com/xdesigner/archive/2006/12/08/586177.html


文章整理:站长天空 网址:http://www.z6688.com/
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

文章页数:[1] 


放大字体显示 缩小字体显示 打印文章 推荐给朋友
热门文章
·Java Unicode转义字符的小小研究-JSP教程,Java技巧及代码
·实现VB与EXCEL的无缝连接-.NET教程,VB.Net语言
·在ASP.NET里通过URL传递参数得到乱码的解决方法-ASP教程,ASP应用
·实例讲解:Java中的SOAP技术-JSP教程,Java技巧及代码
·Session过期问题-ASP教程,ASP应用
·设计模式笔记-抽象工厂模式-.NET教程,评论及其它
·JSP标准标记库促进了网页的开发-JSP教程,Jsp/Servlet
·在Remoting Server上取得Remoting Client的IP地址-ASP教程,ASP应用
·使用JSP标记库校验用户输入-JSP教程,Jsp/Servlet
·c#中DataGrid的数据新增编辑删除操作代码-.NET教程,数据库应用
最新文章
·xp也能享受vista readyboost闪存加速_windows xp
·c# 3.0新特性系列:隐含类型var_c#教程
·如此做google广告,月赚10万美金不成问题_网赚技巧
·王通:个人博客的赚钱之道_网赚技巧
·这一年来风风雨雨-再访中客宋陈磊_站长访谈
·个人网站的定位推广和赚钱-访中国建站站长_站长访谈
·祥瑞网方文春:从800元到6000万元_站长访谈
·行业类、专业性成功网站给个人站长的启示_站长访谈
·网站推广 新招老招齐用上_站长心得
·widnows vista工具栏添加快速启动tabletpc图标_windows vista
相关主题
西部数码虚拟主机

友情链接
CNNIC 西部数码
万网 自助建站
虚拟主机 asp空间
域名注册 域名
域名申请 主页空间
论坛空间 网站空间
国际域名 虚拟空间
空间租用 DDOS防火墙
成都主机托管 四川主机托管
主机租用 服务器租用
网站目录 自助建站
虚拟主机 网址大全
软件下载
自助链接
虚拟主机资讯 特价虚拟主机
版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!
关于我们:站长天空:专业提供最新的站长资讯、在线教程、虚拟主机权威评测、虚拟主机性能对比、网站制作教程,开发教程,站长工具。包括网页制作教程、冲浪宝典、编程参考、操作系统、软件教学、行业动态等。
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
发表评论 打印  刷新     关闭