can't sort files from folder in String[] Array

2019-03-05 18:52发布

问题:

my project is about recording screen as sequence of images then instead of make it as video i planed to load all image directories to list and use timer to view them image by image, but i get files in wrong order like this:

this code is to load files from directory:

string[] array1 = Directory.GetFiles("C:\\Secret\\" + label1.Text, "*.Jpeg");
Array.Sort(array1);

foreach (string name in array1)
{
    listBox1.Items.Add(name);
}
timer2.Start();

this code to view them

        int x = 0;
    private void timer2_Tick(object sender, EventArgs e)
    {
        if (x >= listBox1.Items.Count)
        {
            timer2.Stop();
        }
        else
        {
            ssWithMouseViewer.Image = Image.FromFile(listBox1.Items[x].ToString());

            x++;
        }
    }

i need to view them in order like 0.jpeg, 1.jpeg, 2.jpeg.....10.jpeg, 11..jpeg...

回答1:

The strings are sorted: in lexicographic order...

you have two options: rename the files so they be ordered in lexicographic order (eg: 001, 002, 003...), or, using linq, and file name manipulations:

IEnumerable<string> sorted = from filename in array1
                             orderby int.Parse(Path.GetFileNameWithoutExtension(filename))
                             select filename;


回答2:

Presumably your array should already be sorted as you enter label1.text in numerical order? If not it might be easier for you to sort the label1.text values into numerical order before calling your method.



回答3:

You need to use a "natural sort order" comparer when sorting the array of strings.

The easiest way to do this is to use P/Invoke to call the Windows built-in one, StrCmpLogicalW(), like so (this is a compilable Console application):

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;

namespace ConsoleApp1
{
    [SuppressUnmanagedCodeSecurity]
    internal static class NativeMethods
    {
        [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)]
        public static extern int StrCmpLogicalW(string psz1, string psz2);
    }

    public sealed class NaturalStringComparer: IComparer<string>
    {
        public int Compare(string a, string b)
        {
            return NativeMethods.StrCmpLogicalW(a, b);
        }
    }

    sealed class Program
    {
        void run()
        {
            string[] filenames =
            {
                "0.jpeg",
                "1.jpeg",
                "10.jpeg",
                "11.jpeg",
                "2.jpeg",
                "20.jpeg",
                "21.jpeg"
            };

            Array.Sort(filenames); // Sorts in the wrong order.

            foreach (var filename in filenames)
                Console.WriteLine(filename);

            Console.WriteLine("\n");

            Array.Sort(filenames, new NaturalStringComparer()); // Sorts correctly.

            foreach (var filename in filenames)
                Console.WriteLine(filename);
        }

        static void Main(string[] args)
        {
            new Program().run();
        }
    }
}

NOTE: This example is based on code from this original answer.



回答4:

The most simple way is to use the OrderBy function in LINQ in combination with Path.GetFileNameWithoutExtension like so:

string[] array1 = Directory.GetFiles("C:\\Secret\\" + label1.Text, "*.Jpeg");
array1 = array1.OrderBy(x => int.Parse(System.IO.Path.GetFileNameWithoutExtension(x))).ToArray();

To use the OrderBy function, you need to add a using statement for the namespace System.Linq;



标签: c# timer