PageRenderTime 43ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 1ms

/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. #region Using directives
  18. using System;
  19. using System.Collections;
  20. using System.Collections.Generic;
  21. using System.ComponentModel;
  22. using System.Runtime.InteropServices;
  23. #endregion
  24. namespace CSListFilesInDirectory
  25. {
  26. public class DirectoryEnumerator : IEnumerable<string>
  27. {
  28. #region The Enumerator
  29. public struct Enumerator : IEnumerator<string>
  30. {
  31. #region Private members
  32. private SafeFindHandle hFindFile;
  33. private string current;
  34. private string pattern;
  35. private Mode mode;
  36. #endregion
  37. #region .ctor
  38. internal Enumerator(string pattern, Mode mode)
  39. {
  40. this.pattern = pattern;
  41. this.current = null;
  42. this.hFindFile = null;
  43. this.mode = mode;
  44. }
  45. #endregion
  46. #region IEnumerator<string> Members
  47. public string Current
  48. {
  49. get { return current; }
  50. }
  51. #endregion
  52. #region IDisposable Members
  53. public void Dispose()
  54. {
  55. if (null != hFindFile)
  56. {
  57. hFindFile.Close();
  58. }
  59. }
  60. #endregion
  61. #region IEnumerator Members
  62. object IEnumerator.Current
  63. {
  64. get { return this.Current; }
  65. }
  66. public bool MoveNext()
  67. {
  68. if (null == hFindFile)
  69. {
  70. return FindFirst();
  71. }
  72. else
  73. {
  74. return FindNext();
  75. }
  76. }
  77. public void Reset()
  78. {
  79. if (null != hFindFile)
  80. {
  81. // close the find handle
  82. hFindFile.Close();
  83. hFindFile = null;
  84. }
  85. }
  86. #endregion
  87. #region Supporting methods
  88. /// <summary>
  89. /// Find the first match.
  90. /// </summary>
  91. /// <returns></returns>
  92. private bool FindFirst()
  93. {
  94. WIN32_FIND_DATA fd = new WIN32_FIND_DATA();
  95. hFindFile = NativeMethods.FindFirstFile(pattern, fd);
  96. if (hFindFile.IsInvalid)
  97. {
  98. // Got an invalid find handle, get the error code
  99. int code = Marshal.GetLastWin32Error();
  100. if (code == NativeMethods.ERROR_FILE_NOT_FOUND)
  101. {
  102. // file not found, just return false
  103. return false;
  104. }
  105. // other errors, throw exception
  106. throw new Win32Exception(code);
  107. }
  108. if (!AttributesMatchMode(fd.dwFileAttributes))
  109. {
  110. // if the file does not meet the match mode,
  111. // go find the next match.
  112. return FindNext();
  113. }
  114. current = fd.cFileName;
  115. return true;
  116. }
  117. private bool FindNext()
  118. {
  119. WIN32_FIND_DATA fd = new WIN32_FIND_DATA();
  120. while (NativeMethods.FindNextFile(hFindFile, fd))
  121. {
  122. if (!AttributesMatchMode(fd.dwFileAttributes))
  123. {
  124. // if the file does not meet the match mode,
  125. // go find the next match.
  126. continue;
  127. }
  128. // found a match, return.
  129. current = fd.cFileName;
  130. return true;
  131. }
  132. int code = Marshal.GetLastWin32Error();
  133. if (code == NativeMethods.ERROR_NO_MORE_FILES)
  134. {
  135. // no more files, return false.
  136. return false;
  137. }
  138. // other errors, throw exception.
  139. throw new Win32Exception(code);
  140. }
  141. private bool AttributesMatchMode(int fileAttributes)
  142. {
  143. bool isDir = (fileAttributes & NativeMethods.FILE_ATTRIBUTE_DIRECTORY)
  144. == NativeMethods.FILE_ATTRIBUTE_DIRECTORY;
  145. return ((isDir && (mode & Mode.Directory) == Mode.Directory) ||
  146. (!isDir && (mode & Mode.File) == Mode.File));
  147. }
  148. #endregion
  149. }
  150. #endregion
  151. #region FileEnumeratorMode
  152. [Flags]
  153. public enum Mode
  154. {
  155. /// <summary>
  156. /// Enumerate directories.
  157. /// </summary>
  158. Directory = 1,
  159. /// <summary>
  160. /// Enumerate files.
  161. /// </summary>
  162. File = 2
  163. }
  164. #endregion
  165. #region Private members
  166. private string pattern; // Search pattern
  167. private Mode mode; // Enum mode
  168. #endregion
  169. #region .ctor
  170. public DirectoryEnumerator()
  171. : this("*.*")
  172. {
  173. }
  174. public DirectoryEnumerator(string pattern)
  175. : this(pattern, Mode.Directory | Mode.File)
  176. {
  177. }
  178. public DirectoryEnumerator(string pattern, Mode mode)
  179. {
  180. this.pattern = pattern;
  181. this.mode = mode;
  182. }
  183. #endregion
  184. #region IEnumerable<string> Members
  185. IEnumerator<string> IEnumerable<string>.GetEnumerator()
  186. {
  187. return new Enumerator(pattern, mode);
  188. }
  189. #endregion
  190. #region IEnumerable Members
  191. IEnumerator IEnumerable.GetEnumerator()
  192. {
  193. return ((IEnumerable<string>)this).GetEnumerator();
  194. }
  195. #endregion
  196. }
  197. }