2011-03-10 11 views
6

Como un ejemplo simplificado Estoy ejecutando el siguienteC# ¿EnumerateFiles comodín devuelve no coincidencias?

IEnumerable<string> files = Directory.EnumerateFiles(path, @"2010*.xml", 
    SearchOption.TopDirectoryOnly).ToList(); 

En mi conjunto de resultados que estoy consiguiendo unos ficheros que no puede competir con el patrón de archivo. De acuerdo con msdn searchPattern wildcard es "Cero o más caracteres" y no un reg ex. Un ejemplo es que recibo un nombre de archivo como "2004_someothername.xml".

Para obtener información, hay más de 25,000 archivos en la carpeta.

¿Alguien tiene alguna idea de lo que está pasando?

+1

¿Puede publicar algunos ejemplos de nombres de archivos que coinciden que no deberían? – cptScarlet

+0

Usted dice "como un ejemplo simplificado": ¿ha probado que el código que muestra realmente devolverá el archivo que reclama? ¡Es más probable que el problema se deba al ejemplo no simplificado ...! –

+0

Ejemplo que proporcionaste funciona bien. Solo lo probé. Entonces, si puede publicar un código real que no funciona correctamente – Stecya

Respuesta

8

Esto se debe a la coincidencia de comodines de Windows: incluye los nombres de archivo 8.3 codificados en su búsqueda comodín, lo que da como resultado algunas coincidencias sorprendentes.

Una forma de evitar este error es volver a probar todos los resultados de archivos que vuelven a través de la coincidencia de comodín del sistema operativo y probar con una comparación manual del comodín con cada nombre de archivo (largo). Otra forma es turn off 8.3 filenames altogether via the registry. Me he quemado por esto en numerosas ocasiones, incluyendo que los archivos importantes (que no coinciden) se eliminan a través de un comodín basado en el comando desde el símbolo del sistema. Para resumir, sea muy cuidadoso, especialmente si tiene muchos archivos en un directorio que toman decisiones de producción críticas o que toman acciones basadas en una coincidencia de archivo/comodín del sistema operativo, sin una verificación secundaria de los resultados.

Aquí hay un explanation de este comportamiento extraño.

Otra explicación de O'Reilly's site.

+2

¿Desea vincular el informe de error? –

+3

¿Tiene alguna referencia sobre ese error? No puedo recrearlo en Powershell, con 50,000 archivos, usando la clase system.IO.Directory. –

+0

@All, después de investigar más sobre la causa de esto, actualicé mi respuesta con la explicación del problema y las referencias. –

1

No es una solución para el error MS (que posiblemente utiliza la búsqueda de archivos de Windows debajo, lo cual sería terrible para sus resultados ...), pero una solución como solución, que le da un mayor apalancamiento y control sobre los resultados :

var files = from file in 
     Directory.EnumerateFiles(path, "*", 
     SearchOption.TopDirectoryOnly) 
     where (new FileInfo(file)).Name.StartsWith("2010") && 
      (new FileInfo(file)).Extension == "xml" 
     select dir; 
1

Acabo de intentar su ejemplo y no puedo verlo haciendo nada malo, así que supongo que hay más a su entorno y/o el código "no simplificada" que no está cubierto aquí.

He utilizado este código:

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(); 

En mi estructura de carpetas que he creado el siguiente:

c: \ temp \ test \ 2010 \ 2004_something.xml c: \ temp \ test \ 2010 \ 2010_abc.xml c: \ temp \ test \ 2010 \ 2010_def.xml

la salida de la aplicación es simple:

Starting... 
Found[C:\temp\test\2010\2010_abc.xml] 
Found[C:\temp\test\2010\2010_def.xml] 

¿Puede darnos más comentarios sobre lo que está sucediendo en su escenario, en la aplicación real? o puedes reproducir el problema en una aplicación más pequeña?

2

Puedo reproducir su problema con el siguiente código (Sorry, VB). Crea 55,000 archivos de cero bytes llamados 2000_0001.xml a través de 2010_5000.xml. Luego busca todos los archivos que comienzan en 2010.En mi máquina (Windows 7 SP1 de 32 bits) devuelve 5,174 archivos en lugar de solo 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 
+1

¡Aunque es VB, +1 por el gran esfuerzo! :) –

+2

Me imagino que todos los chicos de C# responden a las preguntas de VB con C# ¡Haría lo contrario! En realidad, eso es justo lo que tenía abierto en este momento. –

0

de haber sufrido el mismo problema, y ​​la búsqueda de este post pensé que iba a publicar mi solución:

IEnumerable<string> Files = Directory.EnumerateFiles(e.FileName, "*.xml").Where(File => File.EndsWith(".xml", StringComparison.InvariantCultureIgnoreCase)); 

Esto sólo pone a prueba el sufijo pero elimina partidos a mis archivos de copia de seguridad que terminan .xml ~.

Cuestiones relacionadas