65.9K
CodeProject 正在变化。 阅读更多。
Home

带线程支持的酷文件系统类 - 易于使用

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.05/5 (8投票s)

2005 年 8 月 22 日

4分钟阅读

viewsIcon

53749

downloadIcon

720

一个易于使用的支持线程的文件系统类。

Sample Image

引言

FileSystem 是一个类,它将使您能够快速、轻松且高效地获取给定目录的内容。文件系统类是任何代码库的重要组成部分。每个应用程序都会进行某种文件交互,如果您创建一个方便的类来处理应用程序和文件系统之间的交互,那么它将使生活更轻松,并且您不必为每个项目反复创建轮子。在这里,我将尝试提供这样一个类,您可以在您的项目中使用它。本文是另一篇文章(使用 Visual Studio .NET 自动执行 MS Excel 2003)的扩展,这两篇文章都属于同一个项目。但是,我对这里提供的代码进行了一些修改,使其更加通用。

所以本文分为两个部分,一个部分将介绍 FileSystem 类,另一个部分将介绍使用该类演示其某些功能的应用程序。

背景

无需背景知识,只需熟悉 C# 语言、线程和 FileSystemObject 即可。

使用代码

在这里,我将尝试介绍 FileSystem 类。这个类非常简单,不言自明。它也有很好的文档记录。但我们还是来看看。所以我们有一个名为 FileSystem 的类,它用于执行一些文件系统操作。我们来看看这个类

FileSystem 类

好了,我们有几个文件是类内部使用的。其中六个作为属性提供,可以在运行时访问,而一些则在初始化时设置,即 sourcePathdestinationPath

  • COPY_STATUS - 用于将复制线程的状态通知给父线程。
  • FILE_FILTER - 用于过滤文件类型。例如 *.xml、*.cs、*.xls 等。如果为 null,则表现为 *.*。
  • NUMBER_OF_DIRECTORIES - 返回搜索中的目录数。
  • NUMBER_OF_FIELS - 返回搜索中的文件数。
  • ROOT_PATH - 获取或设置用于导航的根路径。
  • STATUS - 是 FileSystem 类中主线程的状态。

您还可以注意到有三个私有方法供类内部使用。其中两个方法用于启动特定线程。RecursiveDirectoryNavigation() 方法由 FileSystem 类的主线程使用,根据 rootPath 进行导航。

要使用该类的复制方法,您将使用两个重载的构造函数函数之一,然后调用 copyDirectory 方法,该方法将启动 startCopyThread 来执行操作。从您的主线程,您可以使用 COPY_STATUS 属性来检查线程的状态,以决定下一步的程序逻辑(如果有)。

要使用该代码,您只需要以下内容

CoolFileSystem.FileSystem fileSystem 
               = FileSystem(@root);

就这样!下面您将看到代码片段。当然,完整的源代码可供您下载。下面您可以看到类源代码的一部分。

namespace CoolFileSystem
{
    public class FileSystem
    {
        // Used to hold root directory. Start point for the search.
        private string rootPath;

        ...

        // Used to filter filename when doing
        // the search. By default it is set to "*.xls".
        // Can be changed using the FILE_FILTER property.
        private string fileFilter = "*.*";

        // File list is used internally. It is a list
        // of all files found given the search
        // criteria. Automatically adjust itself. Default size 500.
        private ArrayList fileList = new ArrayList(500);
        
        // Used to store directories found under
        // the rootPath. It contains objects of type
        // DirectoryStructure which hold
        // the Directory Information with a list of files
        // under the current directory.
        private ArrayList directoryList = new ArrayList(500);

        // Used for navigation thru the directory structure.
        private Thread mainThread;
        ...
        
        ...
        public FileSystem(string path)
        {
            rootPath = path;
            mainThread = new Thread(new ThreadStart(startThread));
            mainThread.Start();
        }

        private void startThread()
        {
            DirectoryInfo di = new DirectoryInfo(rootPath);
            RecursiveDirectoryNavigation( di );
        }
        ...
        
        ...
        #region RECURSIVE DIRECTORY NAVIGATION
        [STAThread]
        private void RecursiveDirectoryNavigation( DirectoryInfo di )
        {
            try
            {
                // Add the current directory to the directory list
                DirectoryStructure ds = new DirectoryStructure();
                ds.di = di;

                int insertionIndex = 0;
                // Let's get files in directory
                foreach( FileInfo fi in di.GetFiles(fileFilter) )
                {
                    fileList.Insert(insertionIndex, fi);
                    ds.fileList.Insert(insertionIndex, fi);
                }
                directoryList.Add(ds);
                
                foreach( DirectoryInfo d in di.GetDirectories() )
                {
                    RecursiveDirectoryNavigation( d );
                }
            }
            catch {}
            finally {}
        }
        #endregion

        public ArrayList GetFiles()
        {
            return fileList;
        }

        public ArrayList GetDirectories()
        {
            return directoryList;
        }

        public string GetNumOfFilesCopied()
        {
            return copyNumofFiles.ToString();
        }
    }
    ...

因此,从上面的代码中,您可以预览该类。代码有很好的文档记录,所以我不会深入细节。

在下一节中,我将向您展示该类如何在主代码或驱动程序中使用。在这种情况下,我创建了一个 Windows 应用程序,其中有一个按钮和一些显示类状态的标签。单击按钮时,您将获得 FolderBrowseDialog,允许您选择根目录;一旦您选择了一个有效的根目录,您将获得结果。

DriverCoolFileSystem 类

好的,驱动类用于演示 FileSystem 类的一些功能。您应该关注的方法如下:

  • butRootDirectory_Click - 此函数允许用户选择用于导航的根目录。
  • timer_Tick - 由驱动程序用于检查 FileSystem 类。
  • ListDirectories - 用于填充树视图。

当您运行程序并单击“选择根目录”时,您会看到一个对话框,允许您浏览目录结构。当您进行选择时,将创建一个 FileSystem 对象,并将完整路径通过构造函数发送。然后启动一个计时器,该计时器会检查 FileSystem 对象的状态。下一步是更新 UI。

namespace CoolFileSystem
{
    /// <summary>
    /// Driver for CoolFileSystem
    /// </summary>
    public class DriverCoolFileSystem : System.Windows.Forms.Form
    {

        // Declare variable for CoolFileSystem
        private CoolFileSystem.FileSystem fileSystem = null;

        ...

        public DriverCoolFileSystem()
        {
            InitializeComponent();
        }
        
        ...
        
        private void butRootDirectory_Click(object sender, System.EventArgs e)
        {
            FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
            DialogResult result = folderBrowserDialog.ShowDialog();
            if( result == DialogResult.OK )
            {
                if( this.fileSystem == null )
                {
                    this.fileSystem = 
                      new FileSystem(@folderBrowserDialog.SelectedPath);
                    timer.Start();
                }
                else
                {
                    MessageBox.Show( "File Sys running ...");
                }
            }
        }

        private void timer_Tick(object sender, System.EventArgs e)
        {
            this.lblDirectories.Text = "Num of Directories: " + 
                         this.fileSystem.NUMBER_OF_DIRECTORIES;
            this.lblFiles.Text = "Num of Files: " + 
                         this.fileSystem.NUMBER_OF_FILES;
            this.lblStatus.Text = "Status: " + this.fileSystem.STATUS;
            if( this.fileSystem.STATUS.Equals("Stopped") )
            {
                this.lblStatus.Text = "Status: " + this.fileSystem.STATUS;
                timer.Stop();

                // populate the tree view
                Thread listFolders = 
                   new Thread(new ThreadStart(ListDirectories));
                treeView.Nodes.Clear();
                listFolders.Start();
            }
        }

        private void ListDirectories()
        {
            ArrayList directoryList = this.fileSystem.GetDirectories();

            foreach( DirectoryStructure ds in directoryList )
            {
                if( ds.fileList.Count > 0 )
                {
                    TreeNode folder = new TreeNode(ds.di.Name.ToString());

                    foreach( FileInfo fi in ds.fileList )
                    {
                        TreeNode file = new TreeNode(fi.FullName);
                        folder.Nodes.Add(file);
                    }

                    // Vahe Karamian - 03/01/2005 - This is for Thread Safety
                    if(treeView.InvokeRequired == true)
                    {
                        // check if we running within the same thread
                        treeView.Invoke(new AddToTreeView(treeView.Nodes.Add), 
                            new object[] {folder});
                    }
                    else
                    {
                        treeView.Nodes.Add(folder);
                    }
                }
            }
            this.fileSystem = null;
        }

    }
}

如果您注意到,有一个计时器设置为每秒检查一次文件系统线程的状态。再次强调,代码很简单,我不会深入细节。我希望这个代码示例能为您提供一种不同的文件系统导航方法。

关注点

该类非常灵活,您可以轻松地扩展它并在您自己的程序中使用它。我在当前 CodeProject 版本中删除的一个功能是能够搜索相同类型的文件并获取最新文件进行处理。您需要做一些小的调整才能获得该功能。我提供的这是一个通用的代码基础,每个人都可以使用。

© . All rights reserved.