GetFiles gibt falsche Reihenfolge aus

  • VB.NET

Es gibt 4 Antworten in diesem Thema. Der letzte Beitrag () ist von Bartosz.

    GetFiles gibt falsche Reihenfolge aus

    Hey, ich habe wahrscheinlich mal wieder eine richtig simpel zu beantwortende Frage,

    aber ich bekomme ich nicht so recht hin.
    Ich möchte ganz einfach alle Dateien in einem Ordner samt Unterordnern auflisten. Das klappt auch.
    Leider ist die Reihenfolge der Dateien in meiner Listbox anders, als im Windows Explorer.
    Ich habe schon geschaut und herausgefunden, dass man die Liste scheinbar Numeric sortieren muss, da habe ich aber gerade noch meine Probleme.
    Das ist mein Code bisher:

    VB.NET-Quellcode

    1. If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
    2. FastColoredTextBox1.Clear()
    3. Label1.Text = FastColoredTextBox1.Lines.Count
    4. ListBox1.Items.Clear()
    5. Dim files() As String = IO.Directory.GetFiles(ofd.SelectedPath, "*.*", IO.SearchOption.AllDirectories)
    6. Array.Sort(files)
    7. ListBox1.Items.AddRange(files)
    8. Label1.Text = ListBox1.Items.Count
    9. End If


    VB.NET-Quellcode

    1. Array.Sort(files)


    bringt leider nicht wirklich das Ergebnis wie ich es möchte.

    Beispielsweise habe ich das hier gefunden:
    List(Of FileInfo) nach Name sortieren

    Jedoch bekomme ich diesen Fehler:



    Sonst ein Tipp?

    Vielen Dank..

    Liebe Grüße


    Meine Website:
    www.renebischof.de

    Meine erste App (Android):
    PartyPalooza

    xored schrieb:

    Jedoch bekomme ich diesen Fehler:
    Da musst Du halt die Fehlerbeschreibung lesen, verstehen und dann im Code umsetzen.
    Du versuchst, einer Variable vom Typ Apfel eine Variable vom Typ Birne zuzuweisen.
    Klar, dass das nicht geht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich habe nun eine Lösung gefunden. Man musste "Natural" sortieren.

    Ist zwar Copy Paste, aber für Leute, die das mal sehen. Lösung von dotnetperls:

    Klasse:

    VB.NET-Quellcode

    1. ''' <summary>
    2. ''' Sorts alphanumerically.
    3. ''' </summary>
    4. Public Class AlphanumComparator
    5. Implements IComparer
    6. Public Function Compare(ByVal x As Object,
    7. ByVal y As Object) As Integer Implements IComparer.Compare
    8. ' [1] Validate the arguments.
    9. Dim s1 As String = x
    10. If s1 = Nothing Then
    11. Return 0
    12. End If
    13. Dim s2 As String = y
    14. If s2 = Nothing Then
    15. Return 0
    16. End If
    17. Dim len1 As Integer = s1.Length
    18. Dim len2 As Integer = s2.Length
    19. Dim marker1 As Integer = 0
    20. Dim marker2 As Integer = 0
    21. ' [2] Loop over both Strings.
    22. While marker1 < len1 And marker2 < len2
    23. ' [3] Get Chars.
    24. Dim ch1 As Char = s1(marker1)
    25. Dim ch2 As Char = s2(marker2)
    26. Dim space1(len1) As Char
    27. Dim loc1 As Integer = 0
    28. Dim space2(len2) As Char
    29. Dim loc2 As Integer = 0
    30. ' [4] Collect digits for String one.
    31. Do
    32. space1(loc1) = ch1
    33. loc1 += 1
    34. marker1 += 1
    35. If marker1 < len1 Then
    36. ch1 = s1(marker1)
    37. Else
    38. Exit Do
    39. End If
    40. Loop While Char.IsDigit(ch1) = Char.IsDigit(space1(0))
    41. ' [5] Collect digits for String two.
    42. Do
    43. space2(loc2) = ch2
    44. loc2 += 1
    45. marker2 += 1
    46. If marker2 < len2 Then
    47. ch2 = s2(marker2)
    48. Else
    49. Exit Do
    50. End If
    51. Loop While Char.IsDigit(ch2) = Char.IsDigit(space2(0))
    52. ' [6] Convert to Strings.
    53. Dim str1 = New String(space1)
    54. Dim str2 = New String(space2)
    55. ' [7] Parse Strings into Integers.
    56. Dim result As Integer
    57. If Char.IsDigit(space1(0)) And Char.IsDigit(space2(0)) Then
    58. Dim thisNumericChunk = Integer.Parse(str1)
    59. Dim thatNumericChunk = Integer.Parse(str2)
    60. result = thisNumericChunk.CompareTo(thatNumericChunk)
    61. Else
    62. result = str1.CompareTo(str2)
    63. End If
    64. ' [8] Return result if not equal.
    65. If Not result = 0 Then
    66. Return result
    67. End If
    68. End While
    69. ' [9] Compare lengths.
    70. Return len1 - len2
    71. End Function
    72. End Class



    Und bei meinem Code muss man einfach folgendes tun:

    VB.NET-Quellcode

    1. Array.Sort(files, New AlphanumComparator())


    Funktioniert perfekt.
    Danke :)


    Meine Website:
    www.renebischof.de

    Meine erste App (Android):
    PartyPalooza
    Moin,

    warum so kompliziert?

    VB.NET-Quellcode

    1. Public Shared Function GetFiles(ByVal Dir As String) As List(Of IO.FileInfo)
    2. If Dir.Length = 0 Then Return New List(Of IO.FileInfo)
    3. Return New IO.DirectoryInfo(Dir).GetFiles("*.*", IO.SearchOption.AllDirectories).OrderBy(Function(O) O.Directory.FullName).ThenBy(Function(O) O.Name).ToList
    4. End Function


    Die OrderBy kann man nach Belieben anpassen.

    Achte aber darauf, dass es zu Fehlermeldungen kommt, sobald das Programm keine Berechtigungen in einem Verzeichnis ist.

    Ich würde auch keine ListView verwenden, sondern ein DataGridView. Damit bist du sehr viel flexibler.

    Weise dem DGV über .DataSource einfach die Funktion GetFiles(Dir) als Datenquelle zu und schon wird die alles angezeigt, was zum io.FileInfo Objekt gehört.
    Nicht benötigte Spalten kann man ausblenden.
    @xored Verdammt, ich sehe deine Frage jetzt erst... Mit dem Problem habe ich mich auch auseinandersetzen müssen. Wenn du nicht explizit sortierst, werden die Dateien geladen, wie sie im Tableau der Festplatte liegen. Wir gehen das mal durch:

    Stell dir am Anfang vor, du nimmst die SD-Karte aus deiner Digitalkamera und kopierst die Bilder auf deinen Rechner. Die Dateien heißen vorteilhafterweise IMG0001, IMG0002, IMG0003, und so weiter. Wenn du sie jetzt noch gescheit kopierst, dann sind sie sowohl nach der Eigenschaft
    Namen als auch nach CreationTime richtig (alphabetisch und chronologisch). Wenn dein Programm die Bilder einliest, scheint das egal zu sein, denn IMG0001 wurde früher geschossen als IMG0002 und so weiter, von daher mag das korrekt sein, muss aber nicht. Ich habe es schon erlebt, dass 100 Bilder wie folgt eingelesen wurden
    IMG0002
    IMG0003
    .
    .
    .
    IMG0099
    IMG0001, obwohl ich nichts getan habe. Das ist einfach Windows. Das mach mal jemandem klar :D
    Es können auch weitere Problemchen auftreten: Mal angenommen, du hast beim kopieren ein paar Bilder vergessen und kopierst diese nach. Was die Creation angeht, ist das Bild jetzt am neuesten. Das Beispiel kannst du natürlich auf alle anderen Dateiformate beziehen. Wenn du jetzt nach CreationTime sortierst, hast du es zwar gut gemeint, ist aber leider falsch, denn du brauchst das Aufnahmedatum, sofern es in den Metadaten vorliegt (Creation Time ≠ Aufnahmedatum).
    Oder aber, du bearbeitest jetzt ein Bild, speicherst es mit einem anderen Namen ab und verwirfst das Original. Das heißt, du hast jetzt „zufälligere“ Dateinamen und musst daher reagieren.
    Du solltest also auf jeden Fall deinen Sourcecode die Dateien sortieren lassen.
    Zusammengefasst: Du solltest sortieren, weil die Dateien von vornherein unsortiert eingelesen werden könnten (obwohl sie im Explorer sortiert sein mögen), aber beim sortieren musst du auch aufpassen, nach was du sortierst, da du sonst den nächsten „Fehler“ einbaust.

    Zur Methode List (Of T).Sort(Comparison (Of T))

    Das Prinzip ist ein wiederholter Vergleich von Itempaaren, um einen Integer zu erzeugen, der ihre relative Größe darstellt. In solchen Vergleichen bedeutet ein Wert kleiner als Null, dass das erste Element kleiner als das erste ist, ein Wert größer als Null bedeutet, dass das zweite Element kleiner als das erste Element ist, und Null bedeutet, dass sie gleich sind.
    Im Bild im Anhang geht es sogar darum, nach einer zweiten Eigenschaft zu sortieren, falls das Sortieren nach der 1. Eigenschaft nichts bringt. Deshalb wird in diesem Code die zweite Eigenschaft genau dann verglichen, wenn der Vergleich der ersten Eigenschaft ein Ergebnis von Null ergibt.




    Mir ging es jetzt darum, dir das Gesamtkonstrukt /-Problem darzulegen, denn das musste auch ich erstmal durchdremeln. :thumbup:

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Bartosz“ ()