Elan Sanchez
Elan Sanchez

Reputation: 120

Enumerate Files Ordered by Numbered Filename C#

im having a little trouble Ordering my files, i've researched on Stack overflow and tried all other methods but i keep getting the same problem

Thats my code:

public static List<Bitmap> CogerFotosAlamacenadas()
    {
        List<Bitmap> Lista = new List<Bitmap>();
        DirectoryInfo Directorio = new DirectoryInfo(Environment.CurrentDirectory + "\\Almacenamiento");
        FileInfo[] ListaDeFotos = Directorio.GetFiles("*.bmp");

        Array.Sort(ListaDeFotos, delegate (FileInfo x, FileInfo y)
        {
            return string.Compare(x.Name, y.Name);
        });

        foreach (FileInfo foto in ListaDeFotos)
        {
            Image PlaceHolder = Image.FromFile(foto.FullName);

            Lista.Add((Bitmap)PlaceHolder);

        }


        return Lista;
    }

I have a serie of photos named: "Foto" + numberFrom0To300 + "bmp";

after this code is aplied my list get's the photos ordered by 0_10_100_101_102...

Already tried the default order from .GetFiles() this code and another one found in stack overflow whitout usin array.sort i always get the same result hat odd order number

but i have to order them 0,1,2,3,4... at all cost

does ayone have a good idea how to control it?

Upvotes: 1

Views: 160

Answers (2)

Tim Schmelter
Tim Schmelter

Reputation: 460278

You are comparing strings which is using a lexicographical order, you want to order by the number. Then you have to always parse the relevant substring. You can use LINQ:

FileInfo[] orderedPhotos = Directorio.EnumerateFiles("*.bmp")
    .Where(f => f.Name.Length > "Foto.bmp".Length)
    .Select(f => new { 
        File = f, 
        Number = System.IO.Path.GetFileNameWithoutExtension(f.Name).Substring("Foto".Length)
    })
    .Where(x => x.Number.All(Char.IsDigit))
    .Select(x => new { 
        x.File, 
        Integer = int.Parse(x.Number)
    })
    .OrderBy(x => x.Integer)
    .Select(x => x.File)
    .ToArray();

Upvotes: 1

Dmitrii Bychenko
Dmitrii Bychenko

Reputation: 186823

Quick (but may be dirty - interop required) solution is to sort in different way:

using System.Runtime.InteropServices;
...

[DllImport("shlwapi.dll", CharSet = CharSet.Unicode, ExactSpelling = true)]
private static extern int StrCmpLogicalW(string x, string y);

...

// change your current Array.Sort to this one
Array.Sort(ListaDeFotos, (left, right) => StrCmpLogicalW(left.Name, right.Name));

The trick is that string.Compare compares in lexicographical way (and so "10" < "9") when StrCmpLogicalW provides a kind of logical sort ("10" > "9")

Upvotes: 1

Related Questions