文件搜索中的一个不常见但危险的陷阱

在编程过程中,可能会遇到一些不常见但可能引发问题的情况。例如,使用GetFiles()方法时,如果搜索通配符包含星号(*)并且文件扩展名为三字符长(如*.xml或*.jpg),GetFiles()方法会返回所有以提供的扩展名开始的文件。这意味着搜索*.jpg会返回诸如*.jpg、*.jpg2、*.jpegfileformat等文件。

这种奇怪的行为(认为不太优雅)是为了支持8.3文件名格式。正如某博客所述:“一个名为“alongfilename.longextension”的文件有一个等效的8.3文件名“along~1.lon”。如果过滤扩展名“.lon”,那么上述8.3文件名将是一个匹配项。”这就是GetFiles()方法这样表现的原因。

MSDN官方解释如下:当使用星号通配符字符在searchPattern中(例如"*.txt"),匹配行为取决于指定的文件扩展名的长度。一个具有恰好三个字符的文件扩展名的searchPattern将返回具有三个或更多字符的扩展名的文件,其中前三个字符与searchPattern中指定的文件扩展名匹配。一个具有一个、两个或超过三个字符的文件扩展名的searchPattern只返回具有恰好那个长度的扩展名的文件,并且与searchPattern中指定的文件扩展名匹配。当使用问号通配符字符时,此方法只返回与指定文件扩展名匹配的文件。例如,给定两个文件在目录中,“file1.txt”和“file1.txtother”,一个搜索模式为"file?.txt"只返回第一个文件,而一个搜索模式为"file*.txt"返回两个文件。

在情况下,遇到了一个bug,因为临时将一个XML文件重命名为xxx.XML2222,以便将其从应用程序中移除。程序仍然在读取它,导致它的行为不正确。

解决这个问题的方法

如果想防止这种行为,需要手动检查返回的FileInfo类数组,以移除那些不匹配模式的文件。一个优雅的方法是编写一个MethodInfo扩展到DirectoryInfo类,如下所示:

public static FileInfo[] GetFilesByExactMatchExtension(this DirectoryInfo dinfo, string pSearchWildcard) { FileInfo[] files = dinfo.GetFiles(pSearchWildcard); if (files.Length == 0) return files; string extensionSearch = Path.GetExtension(pSearchWildcard).ToLowerInvariant(); List filtered = new List(); foreach (FileInfo finfo in files) { if (finfo.Extension.ToLowerInvariant() != extensionSearch) continue; filtered.Add(finfo); } return filtered.ToArray(); }

通过这种方式,只需使用DirectoryInfo类的常规GetFiles()方法,现在将找到全新的GetFilesByExactMatchExtension(),它将具有所需的行为。

沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485