简体   繁体   English

如何在 C# 中对文件名进行数字排序?

[英]How to sort filenames numerically in c#?

I have several files in a folder.我在一个文件夹中有几个文件。 By default, they are displayed like this.默认情况下,它们是这样显示的。

1.jpg
11.jpg
2.jpg
21.jpg
...

What I need is that the files are ordered numerically, taking as number to file name我需要的是文件按数字顺序排列,将数字作为文件名

1.jpg
2.jpg
11.jpg
21.jpg

My code我的代码

string path = Server.MapPath("./");
string[] files = Directory.GetFiles(path);

you can use custom Comparer - sample:您可以使用自定义比较器 - 示例:

using System.Text;

var directoryInfo = new DirectoryInfo(@"D:\test");
var fileInfoCollection = directoryInfo
    .GetFiles("*.txt")
    .OrderBy(x => x.Name, new AlphanumComparator());

PrintFiles(fileInfoCollection);

void PrintFiles(IEnumerable<FileInfo> files)
{
    foreach (var file in files)
    {
        Console.WriteLine(file.Name);
    }
}

and the core AlphanumComparator class for your problem - borrowed from stack ( https://stackoverflow.com/a/5402865/1187755 ):和您的问题的核心AlphanumComparator类 - 从堆栈中借用( https://stackoverflow.com/a/5402865/1187755 ):

/*
 * The Alphanum Algorithm is an improved sorting algorithm for strings
 * containing numbers.  Instead of sorting numbers in ASCII order like
 * a standard sort, this algorithm sorts numbers in numeric order.
 *
 * The Alphanum Algorithm is discussed at http://www.DaveKoelle.com
 *
 * Based on the Java implementation of Dave Koelle's Alphanum algorithm.
 * Contributed by Jonathan Ruckwood <jonathan.ruckwood@gmail.com>
 *
 * Adapted by Dominik Hurnaus <dominik.hurnaus@gmail.com> to
 *   - correctly sort words where one word starts with another word
 *   - have slightly better performance
 *
 * Released under the MIT License - https://opensource.org/licenses/MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included
 * in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 */
public class AlphanumComparator : IComparer<string>
{
    private enum ChunkType { Alphanumeric, Numeric };
    private bool InChunk(char ch, char otherCh)
    {
        ChunkType type = ChunkType.Alphanumeric;

        if (char.IsDigit(otherCh))
        {
            type = ChunkType.Numeric;
        }

        if ((type == ChunkType.Alphanumeric && char.IsDigit(ch))
            || (type == ChunkType.Numeric && !char.IsDigit(ch)))
        {
            return false;
        }

        return true;
    }

    public int Compare(string x, string y)
    {
        string s1 = x;
        string s2 = y ;

        if (s1 == null || s2 == null)
        {
            return 0;
        }

        int thisMarker = 0, thisNumericChunk = 0;
        int thatMarker = 0, thatNumericChunk = 0;

        while ((thisMarker < s1.Length) || (thatMarker < s2.Length))
        {
            if (thisMarker >= s1.Length)
            {
                return -1;
            }
            else if (thatMarker >= s2.Length)
            {
                return 1;
            }
            char thisCh = s1[thisMarker];
            char thatCh = s2[thatMarker];

            var thisChunk = new StringBuilder();
            var thatChunk = new StringBuilder();

            while ((thisMarker < s1.Length) && (thisChunk.Length == 0 || InChunk(thisCh, thisChunk[0])))
            {
                thisChunk.Append(thisCh);
                thisMarker++;

                if (thisMarker < s1.Length)
                {
                    thisCh = s1[thisMarker];
                }
            }

            while ((thatMarker < s2.Length) && (thatChunk.Length == 0 || InChunk(thatCh, thatChunk[0])))
            {
                thatChunk.Append(thatCh);
                thatMarker++;

                if (thatMarker < s2.Length)
                {
                    thatCh = s2[thatMarker];
                }
            }

            int result = 0;
            // If both chunks contain numeric characters, sort them numerically
            if (char.IsDigit(thisChunk[0]) && char.IsDigit(thatChunk[0]))
            {
                thisNumericChunk = Convert.ToInt32(thisChunk.ToString());
                thatNumericChunk = Convert.ToInt32(thatChunk.ToString());

                if (thisNumericChunk < thatNumericChunk)
                {
                    result = -1;
                }

                if (thisNumericChunk > thatNumericChunk)
                {
                    result = 1;
                }
            }
            else
            {
                result = thisChunk.ToString().CompareTo(thatChunk.ToString());
            }

            if (result != 0)
            {
                return result;
            }
        }

        return 0;
    }
}

if you have time run benchmark :)如果你有时间运行基准:)

Result:结果:

  • 01.txt 01.txt
  • 1.txt 1.txt
  • 1a1.txt 1a1.txt
  • 1a2.txt 1a2.txt
  • 1a.txt 1a.txt
  • 2.txt 2.txt
  • 3.txt 3.txt
  • 4.txt 4.txt
  • 11.txt 11.txt
  • 21.txt 21.txt
  • aaa.txt aaa.txt
  • bbb01.txt bbb01.txt
  • bbb02.txt bbb02.txt
  • bbb.txt bbb.txt
  • test.txt测试.txt
  • z.txt z.txt

You could try:你可以试试:

string[] files = Directory.GetFiles(YourDirectory).OrderBy(f =>int.Parse(Path.GetFileNameWithoutExtension(f))).ToArray();

Source 资源

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM