确定文件是否存在使用c#和parsingUNCpath

我正在尝试编写一个函数来确定文件是否存在。 这两种方法certificate返回不一致的结果(fileExists()似乎提供了准确的结果,相比isFileFound(),返回误报 – 我会期望一个exception,当试图创build实例)。

protected bool isFileFound(string path, string fileName) { System.IO.FileInfo fi = null; bool found = false; try { fi = new System.IO.FileInfo(path + fileName); found = true; } catch (Exception e) { baselogger.Fatal(e.Message + " " + e.StackTrace + " \n" + path + fileName); } return found; } protected bool fileExists(string path, string pattern) { bool success = false; try { success = File.Exists(path + pattern); } catch (Exception e) { baselogger.Warn(e.Message + " " + e.StackTrace + " " + e.Source); } return success; } 

似乎也无法parsing以下语法的UNCpath: \\ abcserver \ c $ \ xyzfolder \ foo.bar

任何想法为什么uncpath失败这些方法将不胜感激。

您可以为不存在的文件创buildFileInfo。 但是你可以检查FileInfo.Exists属性来确定文件是否存在,例如:

 FileInfo fi = new FileInfo(somePath); bool exists = fi.Exists; 

更新 :在一个简短的testing中,这也适用于UNCpath,例如像这样:

 FileInfo fi = new FileInfo(@"\\server\share\file.txt"); bool exists = fi.Exists; 

您确定该帐户(在您的应用程序正在运行)有权访问该共享。 我认为(默认情况下)需要pipe理权限来访问共享“c $”。

看到这个问题:
你怎么能轻松地检查访问被拒绝.NET中的文件?

这个问题的简短版本是,你不这样做,因为文件系统是不稳定的。 只要尝试打开文件,并捕捉exception,如果失败。

isFileFound方法不起作用的原因是因为您正在使用的FileInfo结构也可用于创build文件。 您可以创build一个FileInfo对象,其中包含一个不存在的文件的所需信息,将其.Create()方法,并且一次性设置所需的属性。

我怀疑UNCpath失败的原因是1)从运行你的应用程序的用户访问pipe理共享的权限问题, 或者 2) $符号抛出该方法,或者是因为它没有被正确input,或者是因为一个错误在底层的.Exists()实现中。

更新:

当我发表这个build议时,我几乎总是会抱怨exceptionperformance。 我们来谈谈这个。 是的,处理例外是昂贵的: 非常昂贵。 在编程中你可以做的事情比较慢。 但是你知道这几件事情是什么? 磁盘和networkingI / O。 这里有一个链接,显示了多less磁盘I / O和networkingI / O成本:

https://gist.github.com/jboner/2841832

 延迟比较数字
 --------------------------
一级caching参考0.5 ns
分支误预测5 ns
 L2高速caching参考7 ns 14x L1高速caching
互斥locking/解锁25 ns
主内存参考100纳秒20倍二级caching,200倍一级caching
用Zippy 3000 ns压缩1K字节
通过1 Gbpsnetworking发送1K字节10,000 ns 0.01 ms
从SSD随机读取4K * 150,000 ns 0.15 ms
从存储器中读取1 MB的内存250,000 ns 0.25 ms
往返同一数据中心500,000 ns 0.5 ms
从SSD中按顺序读取1 MB * 1,000,000 ns 1 ms 4X内存
磁盘寻道10,000,000 ns 10 ms 20x数据中心往返
从磁盘顺序读取1 MB 20,000,000 ns 20 ms 80x内存,20X SSD
发送数据包CA->荷兰 - > CA 150,000,000 ns 150 ms 

如果以纳秒思考不是你的事情,这里有另一个链接,将一个CPU周期标准化为1秒,并从那里缩放:

http://blog.codinghorror.com/the-infinite-space-between-words/

 1个CPU周期0.3 ns 1 s
一级caching访问0.9 ns 3 s
二级caching访问2.8 ns 9 s
 3级caching访问12.9 ns 43 s
主存储器访问120 ns 6分钟
固态磁盘I / O 50-150μs2-6天
旋转磁盘I / O 1-10毫秒1-12个月
互联网:SF到纽约40毫秒4年
互联网:SF到英国81毫秒8年
互联网:SF到AUS 183毫秒19年
 OS virt。 重新启动4 s 423年
 SCSI命令超时30秒3000年
硬件虚拟。  40多年后重启4000年
物理系统重新启动5米32千米 

即使是最好的例外情况,在等待来自磁盘的第一个响应时,也可以访问至less480次的内存,这就是假设一个非常快速的SSD。 我们中的许多人仍然需要旋转硬盘,事情变得更糟,更糟糕。

这只是故事的开始。 当你使用.Exists() ,你会承担这个额外的成本(这是一个额外的工作:当你打开文件时你必须再次做同样的工作)。 你支付这个费用是否存在或不存在,因为磁盘仍然要在它的文件表中查找它。 使用exception方法,您只需支付在发生故障时解除调用堆栈的额外成本。

换句话说,是的:例外是非常昂贵的。 但是与磁盘检查相比,速度还是比较快的,而不是一点点小小的。 谢天谢地,这不太可能会驱动你的应用程序的总体性能……但是我仍然想要为这个特定的任务摆脱“例外是缓慢的”论据。

这可能也可能不是这种情况,但是您是否可以为您的某个案例错误地join您的path文件名。

这个:

成功= File.Exists(path+模式);

VS:

成功= File.Exists(Path.Join(path,pattern));

这可以帮助你:
http://www.codeplex.com/FileDirectoryPath
它是NDepend.Helpers.FilePathDirectory ,其中有一个“path有效性检查API”等可用。

所以我去了

 bool success = File.Exists(path + Filename); 

选项,而不是使用FileInfo路由。

感谢所有的build议!

编辑:那么我只是意识到file.exists工作正常。 这肯定是首选的方法。 下面的代码会让你select让Windows提示用户进行身份validation,如果共享应该在不同的域帐户下访问。 有一天可能会帮助别人,所以我只是把代码留在这里。

如果您需要使用不同的凭据访问UNCpath或pipe理员共享: MSDN

要引导使用WNetAddConnection2,请使用以下代码:

 using System; using System.Runtime.InteropServices; namespace Win32Api { public enum ResourceScope { RESOURCE_CONNECTED = 1, RESOURCE_GLOBALNET, RESOURCE_REMEMBERED, RESOURCE_RECENT, RESOURCE_CONTEXT }; public enum ResourceType { RESOURCETYPE_ANY, RESOURCETYPE_DISK, RESOURCETYPE_PRINT, RESOURCETYPE_RESERVED = 8 }; [Flags] public enum ResourceUsage { RESOURCEUSAGE_CONNECTABLE = 0x00000001, RESOURCEUSAGE_CONTAINER = 0x00000002, RESOURCEUSAGE_NOLOCALDEVICE = 0x00000004, RESOURCEUSAGE_SIBLING = 0x00000008, RESOURCEUSAGE_ATTACHED = 0x00000010, RESOURCEUSAGE_ALL = (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED), }; public enum ResourceDisplayType { RESOURCEDISPLAYTYPE_GENERIC, RESOURCEDISPLAYTYPE_DOMAIN, RESOURCEDISPLAYTYPE_SERVER, RESOURCEDISPLAYTYPE_SHARE, RESOURCEDISPLAYTYPE_FILE, RESOURCEDISPLAYTYPE_GROUP, RESOURCEDISPLAYTYPE_NETWORK, RESOURCEDISPLAYTYPE_ROOT, RESOURCEDISPLAYTYPE_SHAREADMIN, RESOURCEDISPLAYTYPE_DIRECTORY, RESOURCEDISPLAYTYPE_TREE, RESOURCEDISPLAYTYPE_NDSCONTAINER }; [StructLayout(LayoutKind.Sequential)] public class NetResource { public ResourceScope Scope; public ResourceType Type; public ResourceDisplayType DisplayType; public ResourceUsage Usage; public string LocalName; public string RemoteName; public string Comment; public string Provider; }; [Flags] public enum AddConnectionOptions { CONNECT_UPDATE_PROFILE = 0x00000001, CONNECT_UPDATE_RECENT = 0x00000002, CONNECT_TEMPORARY = 0x00000004, CONNECT_INTERACTIVE = 0x00000008, CONNECT_PROMPT = 0x00000010, CONNECT_NEED_DRIVE = 0x00000020, CONNECT_REFCOUNT = 0x00000040, CONNECT_REDIRECT = 0x00000080, CONNECT_LOCALDRIVE = 0x00000100, CONNECT_CURRENT_MEDIA = 0x00000200, CONNECT_DEFERRED = 0x00000400, CONNECT_RESERVED = unchecked((int)0xFF000000), CONNECT_COMMANDLINE = 0x00000800, CONNECT_CMD_SAVECRED = 0x00001000, CONNECT_CRED_RESET = 0x00002000 } public static class NativeMethods { [DllImport("mpr.dll", EntryPoint = "WNetAddConnection2")] public static extern int WNetAddConnection2( NetResource netResource, string password, string username, AddConnectionOptions options); [DllImport("mpr.dll")] public static extern int WNetCancelConnection2(string name, int flags, bool force); } }