我想读取一个指定目录下的前N个文件(例如前20),目录下可能会有上万个文件,怎么做才效率比较高
用Directory.GetFiles()去循环读会不会太占资源了

解决方案 »

  1.   

    可以按文件名排序
    或者按文件修改日期排序也行
    如果不能排序的话,只要得到目录下任意50个文件也行
    我的目的是不想用Directory.GetFiles()之类的方法把文件名全部取到一个数组里去,然后循环取
    因为目录下的文件可能会比较多
      

  2.   

    不用Directory.GetFiles()的话怎么得到文件名呢?
    不得到文件名又怎么排序呢?
      

  3.   

    Shell编程可以试试,用到些API麻烦点
      

  4.   

    FindFirstFileEx Function
    Searches a directory for a file or subdirectory with a name and attributes that match those specified.FindNextFile Function
    Continues a file search from a previous call to the FindFirstFile or FindFirstFileEx functionFindClose FunctionCloses a file search handle opened by the FindFirstFile, FindFirstFileEx, or FindFirstStreamW function
      

  5.   

    你这个问题微软已经意识到了,在.Net 4.0里已经用EnumerateFiles方法解决了。
    不过仅就目前而言,也有办法,而且不需要使用Win32 API,而是用WMI 。
    我不知道你是否使用过WMI,所以把方法也说给你:
    添加引用:System.Management.dll
    然后添加命名空间:using System.Management;
    我给你写了两个方法:        void CsToD1()
            {
                ManagementObjectSearcher mos = new ManagementObjectSearcher(@"select * from cim_datafile where drive='c:' and path='\\windows\\system32\\'");
                int count = 0;
                //看起来返回的是集合,但是因为“延迟”特性,所以并没有枚举所有文件
                foreach (ManagementBaseObject mbo in mos.Get())
                {
                    if (count++ == 20)
                        break;
                    Console.WriteLine(mbo["name"]);
                }
            }        //如果你不懂延迟特性,请使用下面事件驱动的方式
            void CsToD2()
            {
                ManagementObjectSearcher mos = new ManagementObjectSearcher(@"select * from cim_datafile where drive='c:' and path='\\windows\\system32\\'");
                ManagementOperationObserver moo = new ManagementOperationObserver();
                int count = 0;
                moo.ObjectReady += (obj, eve) =>
                {
                    if (count++ == 20)
                        moo.Cancel();
                    ManagementBaseObject mbo = eve.NewObject;
                    Console.WriteLine(mbo["name"]);
                };
                mos.Get(moo);
            }
      

  6.   

    我写了个用API的例子:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Runtime.InteropServices;namespace TestPInvoke
    {
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
            }        private void button1_Click(object sender, EventArgs e)
            {            IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
                long size = 0;
                int files = 0;
                int folders = 0;
                WIN32_FIND_DATA findData;            IntPtr findHandle;            // please note that the following line won't work if you try this on a network folder, like \\Machine\C$
                // simply remove the \\?\ part in this case or use \\?\UNC\ prefix
                findHandle = FindFirstFile(@"c:\*", out findData);
                if (findHandle != INVALID_HANDLE_VALUE)
                {
                    do
                    {
                        if ((findData.dwFileAttributes & FileAttributes.Directory) == 0)
                        {
                            // File
                            files++;                        Console.WriteLine(findData.cFileName + "   " + findData.nFileSizeLow);
                        }                    if (files == 50)
                            break;
                    }
                    while (FindNextFile(findHandle, out findData));
                    FindClose(findHandle);            }                   }        public const int MAX_PATH = 260;
            public const int MAX_ALTERNATE = 14;        [StructLayout(LayoutKind.Sequential)]
            public struct FILETIME
            {
                public uint dwLowDateTime;
                public uint dwHighDateTime;
            }; 
            [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
            public struct WIN32_FIND_DATA
            {
                public FileAttributes dwFileAttributes;
                public FILETIME ftCreationTime;
                public FILETIME ftLastAccessTime;
                public FILETIME ftLastWriteTime;
                public int nFileSizeHigh;
                public int nFileSizeLow;
                public int dwReserved0;
                public int dwReserved1;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_PATH)]
                public string cFileName;
                [MarshalAs(UnmanagedType.ByValTStr, SizeConst = MAX_ALTERNATE)]
                public string cAlternate;
            }
            [DllImport("kernel32", CharSet = CharSet.Unicode)]
            public static extern IntPtr FindFirstFile(string lpFileName, out WIN32_FIND_DATA lpFindFileData);        [DllImport("kernel32", CharSet = CharSet.Unicode)]
            public static extern bool FindNextFile(IntPtr hFindFile, out WIN32_FIND_DATA lpFindFileData);        [DllImport("kernel32", CharSet = CharSet.Unicode)]
            public static extern bool FindClose(IntPtr hFindFile);    }
    }
      

  7.   

    三Win32API函数 FindFirstFile,FindNextFile和FindClose。三个API搭配使用就能遍历文件和子目录了,而且可以遍历的时候随时中止,避免无谓的操作。
    参考