Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. Other Discussions
  3. Clever Code
  4. Queue through all files in a directory (and subdirectories).

Queue through all files in a directory (and subdirectories).

Scheduled Pinned Locked Moved Clever Code
data-structures
12 Posts 6 Posters 44 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Paladin2000

    Here is an easy way to queue all files in a folder (and subfolders). You only need to initialize it with _folders.Enqueue(SomeRootDirectoryInfo); before using it...

    private Queue _folders = new Queue();
    private Queue _files = new Queue();

    public FileInfo NextFile
    {
    get
    {
    lock (_files)
    {
    if (_files.Count != 0)
    return _files.Dequeue();
    else
    {
    lock (_folders)
    {
    while (_folders.Count != 0)
    {
    DirectoryInfo dir = _folders.Dequeue();
    foreach (DirectoryInfo d in dir.GetDirectories())
    _folders.Enqueue(d);
    foreach (FileInfo f in dir.GetFiles())
    _files.Enqueue(f);
    if (_files.Count != 0) return _files.Dequeue();
    }
    }
    }
    }
    return null; //Default
    }
    }

    B Offline
    B Offline
    BobJanova
    wrote on last edited by
    #3

    I quite like this. The tradeoff you pay for not loading everything into memory and enumerating the whole tree up front is that there is no indicator of how far through you are. It would be even cleverer if it implemented IEnumerable<FileInfo> so you can foreach over it:

    class LazyFolderTree : IEnumerable<FileInfo> {
    private Queue<DirectoryInfo> _folders = new Queue<DirectoryInfo>();
    private Queue<FileInfo> _files = new Queue<FileInfo>();

    public LazyFolderTree(DirectoryInfo root) { _folders.Enqueue(root); }

    public FileInfo NextFile {
    get
    {
    lock (_files)
    {
    if (_files.Count != 0)
    return _files.Dequeue();
    else
    {
    lock (_folders)
    {
    while (_folders.Count != 0)
    {
    DirectoryInfo dir = _folders.Dequeue();
    foreach (DirectoryInfo d in dir.GetDirectories())
    _folders.Enqueue(d);
    foreach (FileInfo f in dir.GetFiles())
    _files.Enqueue(f);
    if (_files.Count != 0) return _files.Dequeue();
    }
    }
    }
    }
    return null; //Default
    }
    }

    public IEnumerator<FileInfo> GetEnumerator() { return new Enumerator(this); }
    // I think you need to implement this too?
    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }

    private class Enumerator : IEnumerator<FileInfo> {
    LazyFolderTree host;
    FileInfo current = null;

    Enumerator(LazyFolderTree host) { this.host = host; }
    public bool MoveNext(){ return null != current = host.NextFile; }
    public FileInfo Current { get { return current; } }
    object System.Collections.IEnumerable.Current { get { return current; } }
    public void Reset() { throw new NotSupportedException("Can't reset this enumerator."); }
    }
    }

    J 1 Reply Last reply
    0
    • B BobJanova

      I quite like this. The tradeoff you pay for not loading everything into memory and enumerating the whole tree up front is that there is no indicator of how far through you are. It would be even cleverer if it implemented IEnumerable<FileInfo> so you can foreach over it:

      class LazyFolderTree : IEnumerable<FileInfo> {
      private Queue<DirectoryInfo> _folders = new Queue<DirectoryInfo>();
      private Queue<FileInfo> _files = new Queue<FileInfo>();

      public LazyFolderTree(DirectoryInfo root) { _folders.Enqueue(root); }

      public FileInfo NextFile {
      get
      {
      lock (_files)
      {
      if (_files.Count != 0)
      return _files.Dequeue();
      else
      {
      lock (_folders)
      {
      while (_folders.Count != 0)
      {
      DirectoryInfo dir = _folders.Dequeue();
      foreach (DirectoryInfo d in dir.GetDirectories())
      _folders.Enqueue(d);
      foreach (FileInfo f in dir.GetFiles())
      _files.Enqueue(f);
      if (_files.Count != 0) return _files.Dequeue();
      }
      }
      }
      }
      return null; //Default
      }
      }

      public IEnumerator<FileInfo> GetEnumerator() { return new Enumerator(this); }
      // I think you need to implement this too?
      System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }

      private class Enumerator : IEnumerator<FileInfo> {
      LazyFolderTree host;
      FileInfo current = null;

      Enumerator(LazyFolderTree host) { this.host = host; }
      public bool MoveNext(){ return null != current = host.NextFile; }
      public FileInfo Current { get { return current; } }
      object System.Collections.IEnumerable.Current { get { return current; } }
      public void Reset() { throw new NotSupportedException("Can't reset this enumerator."); }
      }
      }

      J Offline
      J Offline
      Julien Villers
      wrote on last edited by
      #4

      > The tradeoff you pay for not loading everything into memory and enumerating the whole tree up front is that there is no indicator of how far through you are. Isn't there a smart thing to do using 'yield return'? Maybe some C# wizard could answer that...

      'As programmers go, I'm fairly social. Which still means I'm a borderline sociopath by normal standards.' Jeff Atwood

      B 1 Reply Last reply
      0
      • R RobCroll

        Hi Timothy, I think there is something missing. Where does the NextFile method come into it?

        "You get that on the big jobs."

        P Offline
        P Offline
        Paladin2000
        wrote on last edited by
        #5

        NextFile is a property, not a method. It could be used simply as:

        FileInfo myFile = NextFile;

        while (myFile != null)
        {
        //Do stuff!

        myFile = NextFile;
        

        }

        etc...

        R 1 Reply Last reply
        0
        • P Paladin2000

          NextFile is a property, not a method. It could be used simply as:

          FileInfo myFile = NextFile;

          while (myFile != null)
          {
          //Do stuff!

          myFile = NextFile;
          

          }

          etc...

          R Offline
          R Offline
          RobCroll
          wrote on last edited by
          #6

          Ok so you have a property that behaves like a method. I'm guessing the FileInfo class is in a different namespace to system.IO which will cause issues with aliasing. And then what happens when two files in different folders have the same name? I'm sure it is smart code, I just don't get it from the snippet provided. Maybe a more complete example is required?

          "You get that on the big jobs."

          P 1 Reply Last reply
          0
          • R RobCroll

            Ok so you have a property that behaves like a method. I'm guessing the FileInfo class is in a different namespace to system.IO which will cause issues with aliasing. And then what happens when two files in different folders have the same name? I'm sure it is smart code, I just don't get it from the snippet provided. Maybe a more complete example is required?

            "You get that on the big jobs."

            P Offline
            P Offline
            Paladin2000
            wrote on last edited by
            #7

            RobCroll wrote:

            I'm guessing the FileInfo class is in a different namespace to system.IO

            What would make you think that? FileInfo is part of the System.IO namespace.

            RobCroll wrote:

            And then what happens when two files in different folders have the same name?

            Why would that be a problem? The FileInfo class holds the full path to the specific file, no matter what the "short" name is. Yes, you could remove the "get" accessor and turn this property into a parameterless method, also.

            1 Reply Last reply
            0
            • J Julien Villers

              > The tradeoff you pay for not loading everything into memory and enumerating the whole tree up front is that there is no indicator of how far through you are. Isn't there a smart thing to do using 'yield return'? Maybe some C# wizard could answer that...

              'As programmers go, I'm fairly social. Which still means I'm a borderline sociopath by normal standards.' Jeff Atwood

              B Offline
              B Offline
              BobJanova
              wrote on last edited by
              #8

              Yes probably (I think yield return is essentially a way of building an IEnumerable like this but without having to type stuff). I haven't ever used it or really got familiar with it though.

              I 1 Reply Last reply
              0
              • B BobJanova

                Yes probably (I think yield return is essentially a way of building an IEnumerable like this but without having to type stuff). I haven't ever used it or really got familiar with it though.

                I Offline
                I Offline
                Ian Shlasko
                wrote on last edited by
                #9

                BobJanova wrote:

                Yes probably (I think yield return is essentially a way of building an IEnumerable like this but without having to type stuff). I haven't ever used it or really got familiar with it though.

                It's actually pretty simple... It would go something like this:

                public IEnumerable<FileInfo> EnumerateFiles(DirectoryInfo rootDirectory)
                {
                Queue<DirectoryInfo> dirs = new Queue<DirectoryInfo();
                dirs.Enqueue(rootDirectory);

                while (dirs.Count != 0)
                {
                DirectoryInfo dir = dirs.Dequeue();
                foreach (DirectoryInfo d in dir.GetDirectories())
                dirs.Enqueue(d);
                foreach (FileInfo f in dir.GetFiles())
                yield return f;
                }
                }

                (Just typed here, so not tested or debugged)

                Proud to have finally moved to the A-Ark. Which one are you in?
                Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                C 1 Reply Last reply
                0
                • I Ian Shlasko

                  BobJanova wrote:

                  Yes probably (I think yield return is essentially a way of building an IEnumerable like this but without having to type stuff). I haven't ever used it or really got familiar with it though.

                  It's actually pretty simple... It would go something like this:

                  public IEnumerable<FileInfo> EnumerateFiles(DirectoryInfo rootDirectory)
                  {
                  Queue<DirectoryInfo> dirs = new Queue<DirectoryInfo();
                  dirs.Enqueue(rootDirectory);

                  while (dirs.Count != 0)
                  {
                  DirectoryInfo dir = dirs.Dequeue();
                  foreach (DirectoryInfo d in dir.GetDirectories())
                  dirs.Enqueue(d);
                  foreach (FileInfo f in dir.GetFiles())
                  yield return f;
                  }
                  }

                  (Just typed here, so not tested or debugged)

                  Proud to have finally moved to the A-Ark. Which one are you in?
                  Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                  C Offline
                  C Offline
                  ChunkyStool
                  wrote on last edited by
                  #10

                  Why queue the directories? GetDirectories() returns an array, so putting them in a collection seems redundant. Some error handling wouldn't hurt either. If an exception is thrown, the entire operation fails.

                  I 1 Reply Last reply
                  0
                  • C ChunkyStool

                    Why queue the directories? GetDirectories() returns an array, so putting them in a collection seems redundant. Some error handling wouldn't hurt either. If an exception is thrown, the entire operation fails.

                    I Offline
                    I Offline
                    Ian Shlasko
                    wrote on last edited by
                    #11

                    Wasn't meant to be perfect... Just a demonstration on how to use yields.

                    Proud to have finally moved to the A-Ark. Which one are you in?
                    Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                    C 1 Reply Last reply
                    0
                    • I Ian Shlasko

                      Wasn't meant to be perfect... Just a demonstration on how to use yields.

                      Proud to have finally moved to the A-Ark. Which one are you in?
                      Author of the Guardians Saga (Sci-Fi/Fantasy novels)

                      C Offline
                      C Offline
                      ChunkyStool
                      wrote on last edited by
                      #12

                      No biggie. Recursion would be ideal for this scenario. ;)

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups