August 5, 2008

File and Directory Classes

Generally it is best to use the FileSystemInfo (abstract base), FileInfo (for files), and DirectoryInfo (for directories) classes. Here is a class diagram to show how the 3 are related:
These classes are found in the "System.IO" namespace.

The "File" and "Directory" classes are used directly on strings:
Using System.IO;
...
// Determining If A File Is A Directory
private bool IsDirectory(string path)
{
    bool res = ((File.GetAttributes(path) & FileAttributes.Directory) ==
                FileAttributes.Directory);
    return res;
}

File.Exists(filname); // To check if a file exists
Directory.Exists(path) // To check if a directory exists

//To get the last time for the last change to a file use:
File.GetLastWriteTime(fileUri).ToString();
Some Iterators for iterating over Files and/or Directories recursively
public static class FileSystemInfoExtender
{
    // Iterate all files in a path, with 
    // an option to recurse through subdirectories
    public static IEnumerable<FileSystemInfo> 
      IterateFiles(this FileSystemInfo targ, bool recurse)
    {
        if (targ == null)
            throw new ArgumentNullException("targ");

        // return initial target
        yield return targ;

        if (recurse)
        {
            DirectoryInfo diTarg = targ as DirectoryInfo;
            // If targ is a directory
            if (diTarg != null)
            {                   
                // Get its contents as FileSystemInfo objects
                FileSystemInfo[] fsis = TryGetFileSystemInfos(diTarg);
                foreach (FileSystemInfo fsi in fsis)
                {
                    foreach (FileSystemInfo fsiInner in 
                        fsi.IterateFiles(recurse))
                        yield return fsiInner;
                }
            }
        }
    }

    // Iterate all files in a path, with 
    // recurse through subdirectories first
    public static IEnumerable<FileSystemInfo> 
        IterateFilesChildrenFirst(
          this FileSystemInfo targ, 
          bool recurse)
    {
        if (targ == null)
            throw new ArgumentNullException("targ");

        if (recurse)
        {
            DirectoryInfo diTarg = targ as DirectoryInfo;
            // If targ is a directory
            if (diTarg != null)
            {
                // Get its contents as FileSystemInfo objects
                FileSystemInfo[] fsis = TryGetFileSystemInfos(diTarg);
                foreach (FileSystemInfo fsi in fsis)
                {
                    foreach (FileSystemInfo fsiInner in
                        fsi.IterateFilesChildrenFirst(recurse))
                        yield return fsiInner;
                }
            }
        }

        // return initial target
        yield return targ;
    }


    private static FileSystemInfo[] TryGetFileSystemInfos(
      DirectoryInfo diTarg)
    {
        FileSystemInfo[] fsis = new FileSystemInfo[0];
        try
        {
            fsis = diTarg.GetFileSystemInfos();
        }
        catch (Exception ex)
        { 
            LogError("Calling GetFileSystemInfos() on \'" + diTarg.FullName + "\' threw " + 
                "an exception: " + ex.ToString());
        }
        return fsis;
    }

    // Iterate all directories in a path, with
    // an option to recurse through subdirectories
    public static IEnumerable<DirectoryInfo> IterateDirectories(
        this DirectoryInfo diTarg, bool recurse)
    {
        if (diTarg == null)
            throw new ArgumentNullException("diTarg");

        if (recurse) // return its children
        {
            DirectoryInfo[] dirs = TryGetDirectories(diTarg);
            foreach (DirectoryInfo dir in dirs)
            {
                foreach (DirectoryInfo dirInner in 
                    dir.IterateDirectories(recurse))
                {
                    yield return dirInner;
                }
            }
        }
        yield return diTarg; // return the current dir
    }

    private static DirectoryInfo[] TryGetDirectories(
        DirectoryInfo diTarg)
    {
        DirectoryInfo[] dirs = new DirectoryInfo[0];
        try
        {
            dirs = diTarg.GetDirectories();
        }
        catch (Exception ex)
        {
            LogError("Calling GetDirectories() on \'" +
                diTarg.FullName + 
                "\' threw " + 
                "an exception: " + 
                ex.ToString());
        }
        return dirs;
    }
 
    private static void LogError(string exStr)
    {
        Debug.WriteLine(exStr);
    }

    public static bool TryDeleteFileSystemInfo(this FileSystemInfo fsi)
    {
        bool success = true;
        try
        {
            fsi.Delete();
        }
        catch (Exception ex)
        {
            success = false;
            LogError("Delete \'" + 
                fsi.FullName + 
                "\' threw an exception: " +
                ex.ToString());
        }
        return success;
    }
}
for something similar check out the Directory.GetFiles(string path, string searchPattern, SearchOption searchOption); method

#region FileAttributesExtender

public static class FileAttributesExtender
{
    // Return lhs flags plus rhs flags
    public static FileAttributes Union(
        this FileAttributes lhs, FileAttributes rhs)
    {
        return lhs | rhs;
    }

    // Return flags common to lhs and rhs
    public static FileAttributes Intersection(
         this FileAttributes lhs, FileAttributes rhs)
    {
        return lhs & rhs;
    }

    // Return lhs flags minus rhs flags
    public static FileAttributes Difference(
         this FileAttributes lhs, FileAttributes rhs)
    {
        FileAttributes common = lhs & rhs;
        int res = (int)lhs - (int)common;
        return (FileAttributes)(res);
    }

    // Return true if lhs contains all the flags within rhs
    public static bool Contains(
         this FileAttributes lhs, FileAttributes rhs)
    {
        FileAttributes common = lhs & rhs;
        return (common == rhs);
    }

    // Return true if lhs contains one of the flags within rhs
    public static bool ContainsAnyOf(
        this FileAttributes lhs, FileAttributes rhs)
    {
        FileAttributes common = lhs & rhs;
        return ((int)common > 0);
    }

    // NON-extension methods here
    public static FileAttributes FromString(string source)
    {
        FileAttributes res = (FileAttributes)Enum.Parse(
             typeof(FileAttributes), source, true);
        return res;
    }

}

#endregion FileAttributesExtender
Sample usage to delete user files in their 'Temp' directory
private void DeleteTemporaryFiles(string tempPath)
{
  System.IO.DirectoryInfo targ = new 
         System.IO.DirectoryInfo(tempPath);
  bool success = false;
  foreach (System.IO.FileSystemInfo fsi in 
                     targ.IterateFiles(false))
  {
    Debug.Write(fsi.FullName);
    Debug.Write(" Attributes:" + fsi.Attributes.ToString("f"));
    if (!fsi.Attributes.ContainsAnyOf(
           System.IO.FileAttributes.System | 
           System.IO.FileAttributes.Temporary))
    {
      success = true;
      try
      {
        fsi.Delete();
      }
      catch (Exception ex)
      {
        success = false;
        Debug.Write(ex.ToString());
      }
      Debug.Write(success ? " Deleted" : " Could not Delete!");
    }
    Debug.WriteLine("");
  }
}

No comments: