写了一个很简单的文件扫描程序,目的是为了检查所有文件夹里特定的文件是否存在
程序需要扫描几万个文件夹,每个文件夹里都包含了数千个小文件。
程序思路大体是
根据文件夹命名规则,拼出文件完整路径,直接用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();
程序需要扫描几万个文件夹,每个文件夹里都包含了数千个小文件。
程序思路大体是
根据文件夹命名规则,拼出文件完整路径,直接用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();
解决方案 »
- GDI+ 画线整个屏幕卡
- DataGridView的CellValueChanged事件和CurrentCellChanged事件
- 菜鸟请教存储过程的调用
- C# 单纯法
- c#做多个摄像头捕获程序问题
- vs2002调试问题
- 关于静态构造函数,大家帮忙
- 提示asp.net版本不对问题 在线等啊!
- installshield脚本判断是否有安装access
- 求解:ServerVersion = “connection.ServerVersion”引发了“System.InvalidOperationExceptio
- 从网上copy了一段发消息的程序代码,老是调试不通.能找到窗体,不能找到控件,求教
- 数据源的问题
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); }
}
直接将结果写入文件.
问题不是在写数据上,是在执行File.Exists()方法是,判断出错,一些原本存在的文件,仍然返回false。
就像系统有时候打开某个文件是,报“系统资源不足,无法读取该文件”的错误一样。顺便补充一下,存储采用的RAID5。会不会跟RAID卡有关。这个问题是否已经超出C#版范围了,不知道还可以在哪个版问。
如果按照cacaca6 的方法,那内存才是问题,文件数量级在千万级甚至亿,如果把FileInfo全部读取到allFiles里面,再去排除,且不说效率如何,光内存就消耗得不行,估计崩溃。
直接根据文件命名规则判断存在性,性能上肯定更优,但不知道File.Exists实现原理是怎样的,是不是性能跟目标文件所在文件夹的文件数目有线性关系。
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();
string path="e:\\"+dt.Rows[i][0].ToString()+"\\"+dt.Rows[i][1].ToString();
这个写法肯定是没问题的。
看来确实是个棘手问题啊,真的没人知道么?