问题描述
根据Microsoft Docs site for Directory.EnumerateFiles,当精确到3个字符时,搜索模式参数将匹配以指定模式开头的任何扩展名。但是,这不适用于文件共享,仅适用于本地驱动器。
对于\\share\folder\
包含一个名为file.xlsx
的单个文件的目录,此第一个代码段不会返回它:
public static List<string> GetAllFilesFromDirectory(string directory) =>
new[] { "*.csv","*.xls","*.txt" }.SelectMany(ext => Directory.EnumerateFiles(directory,ext)).ToList();
但是,如果我添加了*.xlsx
模式,它将返回它:
public static List<string> GetAllFilesFromDirectory(string directory) =>
new[] { "*.csv","*.xlsx",ext)).ToList();
我还使用C:\temp
目录中的相同文件对此进行了测试,结果发现两种方法都将其返回。
它正在.NET Framework 4.7.2控制台应用程序中运行。
我在搜索模式中缺少什么吗?还是这不适用于与本地驱动器相同的文件共享方式?这会是预期的吗?
解决方法
您必须是最不幸的人,才能遇到此错误。我可以确认它的行为符合您的观察,并且在互连网上的任何地方都找不到对此的引用。
因此,我跟踪了.NET源代码,以了解Directory.EnumerateFiles
的工作方式-深入肠内-最终遇到FindFirstFile
到FindNextFile
以及随后的[DllImport("kernel32.dll",CharSet = CharSet.Unicode)]
public static extern IntPtr FindFirstFile(string lpFileName,out WIN32_FIND_DATA lpFindFileData);
调用。这些是直接从内核调用的,因此您无法获得比这更低的任何东西。
*.xls
那得测试一下。你猜怎么了?它会在本地目录中捕获XLSX文件,但不会在网络共享中捕获。
call也没有提及此行为。嗯是的。您刚刚点击了一个未公开的“功能”:)
编辑:这会变得更好。在 .NET Core (从2.0一直到.NET 5)中,这种行为不再存在。他们实际上这次写了自己的The doc for the function。 FindFirstFile
不会在本地或其他任何文件夹中捕获XLSX。 pattern matcher仍然说应该这样做。
这是我对public class Program
{
public static void Main(string[] args)
{
// Ensure these test folders only contain ONE file.
// Name the file "Test.xlsx"
Test(@"C:\Temp\*.xls"); // Finds the xlsx file just fine
Test(@"\\Server\Temp\*.xls"); // But not here!
}
public static void Test(string fileName)
{
Win32Native.WIN32_FIND_DATA data;
var hnd = Win32Native.FindFirstFile(fileName,out data);
if (hnd == Win32Native.InvalidPtr)
Debug.WriteLine("Not found!!");
else
Debug.WriteLine("Found: " + data.cFileName);
}
}
/** Windows native Pinvoke **/
public class Win32Native
{
public static IntPtr InvalidPtr = new IntPtr(-1);
[DllImport("kernel32.dll",CharSet = CharSet.Auto)]
public static extern IntPtr FindFirstFile(string lpFileName,out WIN32_FIND_DATA lpFindFileData);
[StructLayout(LayoutKind.Sequential,CharSet = CharSet.Auto)]
public struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public System.Runtime.InteropServices.ComTypes.FILETIME ftCreationTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastAccessTime;
public System.Runtime.InteropServices.ComTypes.FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst = 260)]
public string cFileName;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst = 14)]
public string cAlternateFileName;
}
}
通话的测试代码:
@DataJpaTest