1

this is my code:

private void Method1()
{
    int i = 1;
    foreach (string file in Directory.EnumerateFiles(ImagesPath))
    {
        if (Path.GetExtension(file).EndsWith(".png"))
        {
            string image = (Path.GetFullPath(file));
            i += 1;                
        }
    }
}

The imagesPath is a string that binds to a folder which contains images,

Image1.png,
Image2.png
.
.
.
.
Image10.png,
Image11.png
.
.

I want to iterate from Image1.png--->Image2.png, but the foreach iterates Image1.png-->Image10.png-->Image11.png and so forth.

Is there any way to override this?

Alexei Levenkov
  • 98,904
  • 14
  • 127
  • 179
Spymag
  • 105
  • 1
  • 9

3 Answers3

4

You need to strip off the "image" prefix and ".png" suffix, convert what's left to an integer and order on that. For example:

var orderedFiles = Directory
    .EnumerateFiles(ImagesPath)
    //Remove "image" and ".png" and convert the rest to an integer
    .Select(f => int.Parse(f.Replace("image", "").Replace(".png", ""))
    //Order the resultnumerically
    .OrderBy(num => num)
    //Add the "image" prefix and ".png" suffix back in
    .Select(num => string.Format("image{0}.png", num));

foreach(string file in orderedFiles)
{
    //...
}

Additionally, it looks like your directory holds files that are not PNG. Instead of using an if inside your loop, just filter the results in the Directory.EnumerateFiles method:

Directory.EnumerateFiles(ImagesPath, "*.png")
DavidG
  • 113,891
  • 12
  • 217
  • 223
1

This should do the trick as a more general solution

char[] charsToTrim = new char[]{'0','1','2','3','4','5','6','7','8','9'};

List<string> orderedFiles = 
    Directory.EnumerateFiles(ImagesPath)
    // need a copy of the string without the extension or trailing digits
    .Select(str => new { Orig = str, Name = Path.GetFileNameWithoutExtension(str) })
    // anonymous type containing original name, just the text part and just digit part
   .Select(tmp => new { Orig = tmp.Orig, Text = tmp.Name.TrimEnd(charsToTrim), 
            Digits = tmp.Name.Replace(tmp.Name.TrimEnd(charsToTrim), "") })
    // order by the text part
    .OrderBy(tmp => tmp.Text)
    // then by the string digits parsed as int (if no digits, use -1)
    .ThenBy(tmp => tmp.Digits.Any() ? int.Parse(tmp.Digits) : -1)
    // go back to original name
    .Select(tmp => tmp.Orig)
    // return as list
    .ToList();

Now you can do

orderedFiles.Where(fl => Path.GetExtension(fl).ToLowerInvariant() == ".png")` 

to get all the pngs.

TheInnerLight
  • 12,034
  • 1
  • 29
  • 52
0

Can't you just use a for loop? It would be much easier. Something like this:

  • get the path of first file
  • strip it to further reuse
string basic_path=first_image_path.Get_basic_path();

for(int i=0;i<how_many_images;i++){
 path_list.Add(path+i+".png");
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Jaroslaw Weber
  • 105
  • 1
  • 7
  • @AlexeiLevenkov cause you could use the indexer to get the right order, no need to going around with some ugly hack – Jaroslaw Weber Nov 17 '15 at 01:29
  • You should spell out exactly what version of question you are answering. With your edit it makes sense (also I think it does not answer what OP actually need - it is very rare that even if files are saved with sequential numbers then all of them exist) – Alexei Levenkov Nov 17 '15 at 01:53