![](/img/trans.png)
[英]Wildcard returning multiple items EnumerateFiles. Need to be more specific
[英]c# EnumerateFiles wildcard returning non matches?
作為簡化示例,我正在執行以下操作
IEnumerable<string> files = Directory.EnumerateFiles(path, @"2010*.xml",
SearchOption.TopDirectoryOnly).ToList();
在我的結果集中,我得到一些與文件模式不匹配的文件。 根據msdn searchPattern通配符是“零個或多個字符”而不是reg ex。 一個例子是我得到的文件名為“2004_someothername.xml”。
有關信息,文件夾中有超過25,000個文件。
有誰知道發生了什么事?
這是由於Windows如何進行通配符匹配 - 它在通配符搜索中包含編碼的8.3文件名 ,導致一些令人驚訝的匹配!
解決此錯誤的一種方法是重新測試通過OS通配符匹配返回的所有文件結果,並通過手動比較通配符與每個(長)文件名進行測試。 另一種方法是通過注冊表完全關閉8.3文件名 。 我已經在很多場合被燒毀了,包括從命令提示符中通過基於通配符的del命令刪除重要的(不匹配的)文件。
總而言之,要非常小心 ,特別是如果您在目錄中有許多文件做出任何關鍵的生產決策或采取基於操作系統文件/通配符匹配的任何操作,而無需對結果進行二次驗證。
這是對這種奇怪行為的解釋 。
O'Reilly網站的另一個解釋。
我可以使用以下代碼重現您的問題(對不起,VB)。 它通過2010_5000.xml
創建了名為2000_0001.xml
55,000個零字節文件。 然后它查找以2010開頭的所有文件。在我的機器上(Windows 7 SP1 32位),它返回5,174個文件而不是5,000個。
Option Explicit On
Option Strict On
Imports System.IO
Public Class Form1
Private TempFolder As String = Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, "Temp")
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
CreateFiles()
Dim Files = Directory.EnumerateFiles(TempFolder, "2010*.xml", SearchOption.TopDirectoryOnly).ToList()
Using FS As New FileStream(Path.Combine(My.Computer.FileSystem.SpecialDirectories.Desktop, "Report.txt"), FileMode.Create, FileAccess.Write, FileShare.Read)
Using SW As New StreamWriter(FS, System.Text.Encoding.ASCII)
For Each F In Files
SW.WriteLine(F)
Next
End Using
End Using
DeleteFiles()
End Sub
Private Sub CreateFiles()
If Not Directory.Exists(TempFolder) Then Directory.CreateDirectory(TempFolder)
Dim Bytes() As Byte = {}
Dim Name As String
For Y = 2000 To 2010
Trace.WriteLine(Y)
For I = 1 To 5000
Name = String.Format("{0}_{1}.xml", Y, I.ToString.PadLeft(4, "0"c))
File.WriteAllBytes(Path.Combine(TempFolder, Name), Bytes)
Next
Next
End Sub
Private Sub DeleteFiles()
Directory.Delete(TempFolder, True)
End Sub
End Class
不是MS錯誤的解決方案(可能使用下面的Windows文件搜索,這對您的結果來說太糟糕了......),但作為解決方案的解決方案,它為您提供了一些額外的杠桿和對結果的控制:
var files = from file in
Directory.EnumerateFiles(path, "*",
SearchOption.TopDirectoryOnly)
where (new FileInfo(file)).Name.StartsWith("2010") &&
(new FileInfo(file)).Extension == "xml"
select dir;
我只是嘗試了你的例子,我看不出它做錯了什么,所以我想你的環境和/或這里沒有涉及的“非簡化”代碼還有更多。
我用過這段代碼:
Console.WriteLine("Starting...");
IEnumerable<string> files = Directory.EnumerateFiles("C:\\temp\\test\\2010", @"2010*.xml", SearchOption.TopDirectoryOnly).ToList();
foreach (string file in files)
{
Console.WriteLine("Found[{0}]", file);
}
Console.ReadLine();
在我的文件夾結構中,我創建了以下內容:
c:\\ temp \\ test \\ 2010 \\ 2004_something.xml c:\\ temp \\ test \\ 2010 \\ 2010_abc.xml c:\\ temp \\ test \\ 2010 \\ 2010_def.xml
應用程序的輸出只是:
Starting...
Found[C:\temp\test\2010\2010_abc.xml]
Found[C:\temp\test\2010\2010_def.xml]
您能否在實際應用中提供更多關於您的方案中發生的事情的反饋? 或者你可以在較小的應用程序中重現問題?
遇到了同樣的問題,發現這篇文章,我想我會發布我的解決方案:
IEnumerable<string> Files = Directory.EnumerateFiles(e.FileName, "*.xml").Where(File => File.EndsWith(".xml", StringComparison.InvariantCultureIgnoreCase));
這僅測試后綴,但消除了與以.xml~結尾的備份文件的匹配。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.