国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

C#使用WIN32API來(lái)遍歷文件和目錄

2019-11-18 16:49:49
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

我們有時(shí)需要遍歷某個(gè)目錄下的文件和子目錄,可以使用System.IO.DirectoryInfo.GetDirectories或GetFiles來(lái)獲得目錄下的所有的文件和子目錄,當(dāng)這個(gè)目錄下的內(nèi)容比較多時(shí),這個(gè)操作就比較耗時(shí)間,有時(shí)我們僅僅需要知道某個(gè)目錄下是否有子目錄,這樣的操作顯然是浪費(fèi)時(shí)間的。此時(shí)我們很容易想到三個(gè)Win32API函數(shù) FindFirstFile,F(xiàn)indNextFile和FindClose。這三個(gè)API搭配使用就能遍歷文件和子目錄了,而且可以遍歷的時(shí)候隨時(shí)中止,避免無(wú)謂的操作。

C#中可以使用foreach來(lái)遍歷某個(gè)序列,遍歷使用的對(duì)象必須實(shí)現(xiàn) System.Collections.IEnumeable接口,而內(nèi)部調(diào)用的遍歷器則必須實(shí)現(xiàn)System.Collections.IEnumerator , 為了使用方便,我們?cè)谑褂肍indFirstFile等API函數(shù)時(shí)封裝為 IEnumerator,而且實(shí)際上是有條件封裝的。

這里很多人就會(huì)提到C#調(diào)用API的執(zhí)行效率問(wèn)題,認(rèn)為應(yīng)當(dāng)用C,C++調(diào)用API才是正道,使用C#調(diào)用則有些雞肋。但在我個(gè)人編程經(jīng)歷中,也有不少調(diào)用API的,經(jīng)驗(yàn)發(fā)現(xiàn)其實(shí)效率問(wèn)題不大,可以省略。我只是做常規(guī)的運(yùn)行在PC機(jī)上面的軟件,CPU通常超過(guò)1GHZ,而且無(wú)需考慮高實(shí)時(shí)性和高效率。若過(guò)于考慮效率問(wèn)題會(huì)加大軟件開(kāi)發(fā)消耗。從工程開(kāi)發(fā)管理方面看是不合理的。我應(yīng)當(dāng)解決比較突出的效率問(wèn)題,不突出的影響不大的效率問(wèn)題有時(shí)間才去解決。使用C#封裝Win32API必然會(huì)降低執(zhí)行效率,但是封裝后使用方便快捷,綜合考慮認(rèn)為這是正確的。

這里說(shuō)一下“技術(shù)鍍金”這個(gè)問(wèn)題,所謂技術(shù)鍍金就是開(kāi)發(fā)人員在項(xiàng)目軟件開(kāi)發(fā)中過(guò)于追求技術(shù)的完美性,試圖在技術(shù)上鍍上一層完美的金殼,導(dǎo)致軟件開(kāi)發(fā)工作量加大,項(xiàng)目時(shí)間拉長(zhǎng),有可能導(dǎo)致項(xiàng)目的失敗。我吃過(guò)“技術(shù)鍍金”的苦頭,現(xiàn)在我內(nèi)心是追求完美的,但實(shí)際開(kāi)發(fā)時(shí)經(jīng)常有意壓制追求完美的心思。

現(xiàn)在繼續(xù)探討封裝大計(jì),本次封裝重點(diǎn)在于實(shí)現(xiàn)IEnumerator,而IEnumeable只是IEnumerator的一個(gè)包裝。IEnumerator實(shí)現(xiàn)方法 Reset , MoveNext 和屬性 Current,Reset方法用于重新設(shè)置遍歷器,MoveNext用于查找下一個(gè)文件或目錄,而Current返回當(dāng)前文件或目錄。

這個(gè)遍歷器還得注意FindClose的調(diào)用,必須在遍歷完畢沒(méi)有找到文件或子目錄后調(diào)用,若不調(diào)用該API函數(shù)則會(huì)造成內(nèi)存泄漏。

根據(jù)上述設(shè)計(jì),我寫(xiě)出如下代碼,這段代碼功能單一,希望有人能用得上

 

/// <summary>
/// 文件或目錄遍歷器,本類型為 FileDirectoryEnumerator 的一個(gè)包裝
/// </summary>
/// <remarks>
///
/// 編寫(xiě) 袁永福 ( http://www.xdesigner.cn )2006-12-8
///
/// 以下代碼演示使用這個(gè)文件目錄遍歷器
///
/// 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>
    /// 是否以字符串方式返回查詢結(jié)果,若返回true則當(dāng)前對(duì)象返回為字符串,
    /// 否則返回 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>
    /// 搜索路徑,必須為絕對(duì)路徑
    /// </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>
    /// 發(fā)生IO錯(cuò)誤時(shí)是否拋出異常
    /// </summary>
    public bool ThrowIOException
    {
        get { return this.bolThrowIOException; }
        set { this.bolThrowIOException = value; }
    }
    /// <summary>
    /// 返回內(nèi)置的文件和目錄遍歷器
    /// </summary>
    /// <returns>遍歷器對(duì)象</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>
    /// 關(guān)閉對(duì)象
    /// </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>本對(duì)象為Win32API函數(shù) FindFirstFile , FindNextFile
/// 和 FindClose 的一個(gè)包裝
///
/// 以下代碼演示使用了 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();
///
/// 編寫(xiě) 袁永福 ( http://www.xdesigner.cn )2006-12-8</remarks>
public class FileDirectoryEnumerator : System.Collections.IEnumerator
{
   
    #region 表示對(duì)象當(dāng)前狀態(tài)的數(shù)據(jù)和屬性 **********************************

    /// <summary>
    /// 當(dāng)前對(duì)象
    /// </summary>
    private object objCurrentObject = null;

    private bool bolIsEmpty = false;
    /// <summary>
    /// 該目錄為空
    /// </summary>
    public bool IsEmpty
    {
        get { return bolIsEmpty; }
    }
    private int intSearchedCount = 0;
    /// <summary>
    /// 已找到的對(duì)象的個(gè)數(shù)
    /// </summary>
    public int SearchedCount
    {
        get { return intSearchedCount; }
    }
    private bool bolIsFile = true;
    /// <summary>
    /// 當(dāng)前對(duì)象是否為文件,若為true則當(dāng)前對(duì)象為文件,否則為目錄
    /// </summary>
    public bool IsFile
    {
        get { return bolIsFile; }
    }
    private int intLastErrorCode = 0;
    /// <summary>
    /// 最后一次操作的Win32錯(cuò)誤代碼
    /// </summary>
    public int LastErrorCode
    {
        get { return intLastErrorCode; }
    }
    /// <summary>
    /// 當(dāng)前對(duì)象的名稱
    /// </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>
    /// 當(dāng)前對(duì)象屬性
    /// </summary>
    public System.IO.FileAttributes Attributes
    {
        get { return (System.IO.FileAttributes)myData.dwFileAttributes; }
    }
    /// <summary>
    /// 當(dāng)前對(duì)象創(chuàng)建時(shí)間
    /// </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>
    /// 當(dāng)前對(duì)象最后訪問(wèn)時(shí)間
    /// </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>
    /// 當(dāng)前對(duì)象最后保存時(shí)間
    /// </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>
    /// 當(dāng)前文件長(zhǎng)度,若為當(dāng)前對(duì)象為文件則返回文件長(zhǎng)度,若當(dāng)前對(duì)象為目錄則返回0
    /// </summary>
    public long FileLength
    {
        get
        {
            if (this.bolIsFile)
                return ToLong(myData.nFileSizeHigh, myData.nFileSizeLow);
            else
                return 0;
        }
    }

    #endregion

    #region 控制對(duì)象特性的一些屬性 ****************************************

    private bool bolThrowIOException = true;
    /// <summary>
    /// 發(fā)生IO錯(cuò)誤時(shí)是否拋出異常
    /// </summary>
    public bool ThrowIOException
    {
        get { return this.bolThrowIOException; }
        set { this.bolThrowIOException = value; }
    }
    private bool bolReturnStringType = true;
    /// <summary>
    /// 是否以字符串方式返回查詢結(jié)果,若返回true則當(dāng)前對(duì)象返回為字符串,
    /// 否則返回 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>
    /// 搜索的父目錄,必須為絕對(duì)路徑,不得有通配符,該目錄必須存在
    /// </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>
    /// 關(guān)閉對(duì)象,停止搜索
    /// </summary>
    public void Close()
    {
        this.CloseHandler();
    }

    #region IEnumerator 成員 **********************************************

    /// <summary>
    /// 返回當(dāng)前對(duì)象
    /// </summary>
    public object Current
    {
        get { return objCurrentObject ; }
    }
    /// <summary>
    /// 找到下一個(gè)文件或目錄
    /// </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>
    /// 重新設(shè)置對(duì)象
    /// </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函數(shù)以及結(jié)構(gòu) **************************************

    [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 內(nèi)部代碼群 ****************************************************

    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>
    /// 開(kāi)始搜索標(biāo)志
    /// </summary>
    private bool bolStartSearchFlag = false;
    /// <summary>
    /// 關(guān)閉內(nèi)部句柄
    /// </summary>
    private void CloseHandler()
    {
        if (this.intSearchHandler != INVALID_HANDLE_VALUE)
        {
            FindClose(this.intSearchHandler);
            this.intSearchHandler = INVALID_HANDLE_VALUE;
        }
    }
    /// <summary>
    /// 開(kāi)始搜索
    /// </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>
    /// 搜索下一個(gè)
    /// </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>
    /// 更新當(dāng)前對(duì)象
    /// </summary>
    /// <returns>操作是否成功</returns>
    private bool UpdateCurrentObject()
    {
        if (intSearchHandler == INVALID_HANDLE_VALUE)
            return false;
        bool Result = false;
        this.objCurrentObject = null;
        if ((myData.dwFileAttributes & 0x10) == 0)
        {
            // 當(dāng)前對(duì)象為文件
            this.bolIsFile = true;
            if (this.bolSearchForFile)
                Result = true;
        }
        else
        {
            // 當(dāng)前對(duì)象為目錄
            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.survivalescaperooms.com/xdesigner/archive/2006/12/08/586177.html


發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 额尔古纳市| 连南| 双流县| 乌恰县| 沙田区| 海丰县| 霞浦县| 郴州市| 辽源市| 多伦县| 固原市| 汉源县| 德惠市| 苗栗市| 华容县| 前郭尔| 奎屯市| 太仆寺旗| 陆川县| 永仁县| 当涂县| 鲁山县| 宿州市| 衡山县| 宜川县| 丘北县| 中江县| 深圳市| 杨浦区| 普陀区| 桂东县| 镇原县| 厦门市| 伽师县| 安泽县| 集安市| 贡山| 巴中市| 五莲县| 浙江省| 阜阳市|