PageRenderTime 27ms CodeModel.GetById 15ms app.highlight 8ms RepoModel.GetById 2ms app.codeStats 0ms

/Visual Studio 2008/CSListFilesInDirectory/FileEnumerator.cs

#
C# | 252 lines | 160 code | 55 blank | 37 comment | 19 complexity | f8e42182bea971afba104fe6b1c7022c MD5 | raw file
  1/************************************* Module Header **************************************\
  2* Module Name:  FileEnumerator.cs
  3* Project:      CSListFilesInDirectory
  4* Copyright (c) Microsoft Corporation.
  5* 
  6* The CSListFilesInDirectory project demonstrates how to implement an IEnumerable<string>
  7* that utilizes the Win32 File Management functions to enable application to get files and
  8* sub-directories in a specified directory one item a time.
  9* 
 10* This source is subject to the Microsoft Public License.
 11* See http://www.microsoft.com/opensource/licenses.mspx#Ms-PL.
 12* All other rights reserved.
 13* 
 14* History:
 15* * 7/7/2009 8:00 PM Jie Wang Created
 16\******************************************************************************************/
 17
 18#region Using directives
 19using System;
 20using System.Collections;
 21using System.Collections.Generic;
 22using System.ComponentModel;
 23using System.Runtime.InteropServices;
 24#endregion
 25
 26
 27namespace CSListFilesInDirectory
 28{
 29    public class DirectoryEnumerator : IEnumerable<string>
 30    {
 31        #region The Enumerator
 32
 33        public struct Enumerator : IEnumerator<string>
 34        {
 35            #region Private members
 36
 37            private SafeFindHandle hFindFile;
 38            private string current;
 39            private string pattern;
 40            private Mode mode;
 41
 42            #endregion
 43
 44            #region .ctor
 45
 46            internal Enumerator(string pattern, Mode mode)
 47            {
 48                this.pattern = pattern;
 49                this.current = null;
 50                this.hFindFile = null;
 51                this.mode = mode;
 52            }
 53
 54            #endregion
 55
 56            #region IEnumerator<string> Members
 57
 58            public string Current
 59            {
 60                get { return current; }
 61            }
 62
 63            #endregion
 64
 65            #region IDisposable Members
 66
 67            public void Dispose()
 68            {
 69                if (null != hFindFile)
 70                {
 71                    hFindFile.Close();
 72                }
 73            }
 74
 75            #endregion
 76
 77            #region IEnumerator Members
 78
 79            object IEnumerator.Current
 80            {
 81                get { return this.Current; }
 82            }
 83
 84            public bool MoveNext()
 85            {
 86                if (null == hFindFile)
 87                {
 88                    return FindFirst();
 89                }
 90                else
 91                {
 92                    return FindNext();
 93                }
 94            }
 95
 96            public void Reset()
 97            {
 98                if (null != hFindFile)
 99                {
100                    // close the find handle
101                    hFindFile.Close();
102                    hFindFile = null;
103                }
104            }
105
106            #endregion
107
108            #region Supporting methods
109
110            /// <summary>
111            /// Find the first match.
112            /// </summary>
113            /// <returns></returns>
114            private bool FindFirst()
115            {
116                WIN32_FIND_DATA fd = new WIN32_FIND_DATA();
117
118                hFindFile = NativeMethods.FindFirstFile(pattern, fd);
119
120                if (hFindFile.IsInvalid)
121                {
122                    // Got an invalid find handle, get the error code
123                    int code = Marshal.GetLastWin32Error();
124
125                    if (code == NativeMethods.ERROR_FILE_NOT_FOUND)
126                    {
127                        // file not found, just return false
128                        return false;
129                    }
130
131                    // other errors, throw exception
132                    throw new Win32Exception(code);
133                }
134
135                if (!AttributesMatchMode(fd.dwFileAttributes))
136                {
137                    // if the file does not meet the match mode,
138                    // go find the next match.
139                    return FindNext();
140                }
141
142                current = fd.cFileName;
143                return true;
144            }
145
146            private bool FindNext()
147            {
148                WIN32_FIND_DATA fd = new WIN32_FIND_DATA();
149
150                while (NativeMethods.FindNextFile(hFindFile, fd))
151                {
152                    if (!AttributesMatchMode(fd.dwFileAttributes))
153                    {
154                        // if the file does not meet the match mode,
155                        // go find the next match.
156                        continue;
157                    }
158
159                    // found a match, return.
160                    current = fd.cFileName;
161                    return true;
162                }
163                
164                int code = Marshal.GetLastWin32Error();
165
166                if (code == NativeMethods.ERROR_NO_MORE_FILES)
167                {
168                    // no more files, return false.
169                    return false;
170                }
171                
172                // other errors, throw exception.
173                throw new Win32Exception(code);
174            }
175
176            private bool AttributesMatchMode(int fileAttributes)
177            {
178                bool isDir = (fileAttributes & NativeMethods.FILE_ATTRIBUTE_DIRECTORY) 
179                    == NativeMethods.FILE_ATTRIBUTE_DIRECTORY;
180
181                return ((isDir && (mode & Mode.Directory) == Mode.Directory) ||
182                    (!isDir && (mode & Mode.File) == Mode.File));
183            }
184
185            #endregion
186        }
187
188        #endregion
189
190        #region FileEnumeratorMode
191
192        [Flags]
193        public enum Mode
194        {
195            /// <summary>
196            /// Enumerate directories.
197            /// </summary>
198            Directory = 1,
199            /// <summary>
200            /// Enumerate files.
201            /// </summary>
202            File = 2
203        }
204
205        #endregion
206
207        #region Private members
208
209        private string pattern; // Search pattern
210        private Mode mode;      // Enum mode
211
212        #endregion
213
214        #region .ctor
215
216        public DirectoryEnumerator()
217            : this("*.*")
218        {
219        }
220
221        public DirectoryEnumerator(string pattern)
222            : this(pattern, Mode.Directory | Mode.File)
223        {            
224        }
225
226        public DirectoryEnumerator(string pattern, Mode mode)
227        {
228            this.pattern = pattern;
229            this.mode = mode;
230        }
231
232        #endregion
233
234        #region IEnumerable<string> Members
235
236        IEnumerator<string> IEnumerable<string>.GetEnumerator()
237        {
238            return new Enumerator(pattern, mode);
239        }
240
241        #endregion
242
243        #region IEnumerable Members
244
245        IEnumerator IEnumerable.GetEnumerator()
246        {
247            return ((IEnumerable<string>)this).GetEnumerator();
248        }
249
250        #endregion
251    }
252}