写了一个很简单的文件扫描程序,目的是为了检查所有文件夹里特定的文件是否存在
程序需要扫描几万个文件夹,每个文件夹里都包含了数千个小文件。
程序思路大体是
根据文件夹命名规则,拼出文件完整路径,直接用System.IO.File.Exist(Path)方法来判断文件是否存在,如不存在,则输出拼出的路径到一个日志文件中。程序逻辑上应该是没有问题的
拿几百个文件做测试也通过
但正式扫描时,运行也没问题,就是结果里面,N多明明文件存在,但被判断为不存在而输入到日志里。
且运行完扫描程序后,系统就处于崩溃状态
初步认为,是扫描程序消耗了大量系统资源,在判断的时候,由于系统资源暂时不可用而导致误判。
目标系统是windows2003 Server 扫描的分区是NTFS分区下面是程序代码示例StringBuilder sb=new StringBuilder();
//dt是包含文件路径的DataTable,约几万条
for(int i=0;i<dt.Rows.Count;i++)
{
  string path="e:/"+dt.Rows[i][0].ToString()+"/"+dt.Rows[i][1].ToString();
  Console.WriteLine("Checking "+path);
  if(!File.Exists(path))
    sb.Append(path+"\t不存在\r\n");
}
StreamWriter sw=new StreamWriter("e:/scanbk.log",false,Encoding.UTF8);
sw.WriteLine(sb.ToString());
sw.Flush();
sw.Close();

解决方案 »

  1.   

    搂主可以用Linq来试试,不用自己写这么多的代码using System;
    using System.Linq;
    using System.IO;...
    ...
    List<FileInfo> allFiles = new List<FileInfo>();
    string thePath = @" .. 你想查的路径";
    DirectoryInfo di = new DirectoryInfo(thePath);
    // 把所有的你想查的路径底下的文件全部放到allFiles里面
    takeAllFiles(di);
    // 把所有的你存在dt.Rows里面的文件名村到一个string[]里面
    var yourFiles = dt.Rows.select(s=>"e:/"+s[i][0].ToString()+"/"+s[i][1].ToString()).ToArray();然后用Except选出来就好了,超级简单
    var result = yourFiles.Except(allFiles.FullName).ToArray();// result就是所有在指定目录下不存在的文件// 用递归的方法把所有文件名选出来放到allFiles里面
    private void takeAllFiles(DirectoryInfo dir)
    {
      foreach (var v in dir.GetFiles().ToArray())
      { allFiles.Add(v);  }
      foreach (var v in dir.GetDirectories())
      {   takeAllFiles(v);  }
    }
      

  2.   

    要是内存不够的问题,可以不要用缓存StringBuilder sb=new StringBuilder();
    直接将结果写入文件.
      

  3.   

    内存肯定够,结果能正常写到文件里面。
    问题不是在写数据上,是在执行File.Exists()方法是,判断出错,一些原本存在的文件,仍然返回false。
    就像系统有时候打开某个文件是,报“系统资源不足,无法读取该文件”的错误一样。顺便补充一下,存储采用的RAID5。会不会跟RAID卡有关。这个问题是否已经超出C#版范围了,不知道还可以在哪个版问。
      

  4.   


    如果按照cacaca6 的方法,那内存才是问题,文件数量级在千万级甚至亿,如果把FileInfo全部读取到allFiles里面,再去排除,且不说效率如何,光内存就消耗得不行,估计崩溃。
    直接根据文件命名规则判断存在性,性能上肯定更优,但不知道File.Exists实现原理是怎样的,是不是性能跟目标文件所在文件夹的文件数目有线性关系。
      

  5.   

    仔细看了看..LZ的错误我以为在这里
    string path="e:/"+dt.Rows[i][0].ToString()+"/"+dt.Rows[i][1].ToString();string path="e://"+dt.Rows[i][0].ToString()+"//"+dt.Rows[i][1].ToString();
      

  6.   

    应该是这个吧?
    string path="e:\\"+dt.Rows[i][0].ToString()+"\\"+dt.Rows[i][1].ToString(); 
      

  7.   

    楼上的,在C#中,类unix路径也可以识别的
    这个写法肯定是没问题的。
    看来确实是个棘手问题啊,真的没人知道么?