1

在一个文件夹中,我有这些文件。windows资源管理器上的顺序是:

  • 输入 (1).jpg
  • 输入 (2).jpg
  • 输入 (101).jpg

这是我从文件夹中获取文件的方式:

var files = Directory.GetFiles(inputImage, "*.*", SearchOption.TopDirectoryOnly);

但顺序将是:

  • 输入 (1).jpg
  • 输入 (101).jpg
  • 输入 (2).jpg

即使我尝试过:Array.Sort(files);

但是顺序是一样的,我怎样才能用这个顺序加载文件:

  • 输入 (1).jpg
  • 输入 (2).jpg
  • 输入 (101).jpg
4

7 回答 7

2

好吧,我会尝试这样的事情:

        var files = from file in directoryInfo.EnumerateFiles()
        .Where(f => f.Extension == ".jpg")
                    orderby ExtractNumber(file.Name) ascending
                    select file.FullName;
        return files.ToList<string>();

这里我们提取文件号 - 在 ( 和 )- 之间。

private static object ExtractNumber(string p)
{
    int lenght = p.IndexOf(')') - p.IndexOf('(');
    return int.Parse(p.Substring(p.IndexOf('('), lenght - 1)); 
}

我很确定必须有一种有效的方法来做到这一点,但只是我的两分钱。

于 2012-06-18T15:05:07.140 回答
2

您需要实现自己的比较,以“意识到”它们包含嵌入的非零填充数字的方式比较两个字符串。Explorer 已经包含此逻辑,并且(根据评论)这是公开的StrCmpLogicalW,您可以在其中使用P/Invoke在自定义Comparer<string>实现中调用,您可以将其传递给排序方法。

如果您知道有关名称的所有其他信息(即模式),那么很容易去除固定部分进行比较 - 但StrCmpLogicalW会给您一个很好的通用实现。

当然,如果您可以控制创建文件的任何内容,则更简单的方法是将文件名零填充到一些合理的数字,例如 5 或 6。

于 2012-06-18T14:56:43.807 回答
2

如果您以简单的方式加载文件:

string[] files = Directory.GetFiles ("folder");

并假设括号中总是有一个数字,您可以使用一个函数:

Array.Sort (files, compareFilesWithBrackets);

带比较功能:

public static int compareFilesWithBrackets (string arg1, string arg2)
{
        string filename1 = System.IO.Path.GetFileName (arg1); //extract filename from the path of the first file
        string filename2 = System.IO.Path.GetFileName (arg2); // extract second file filename
        Match m = Regex.Match (filename1, "\\(([0-9]+)\\)"); // check if there is (number) for file 1
        int file1 = 0; // if no number leave 0
        if (m.Success) { // else if success parse the number from brackets
            file1 = int.Parse (m.Groups [1].Value); 
        }
        m = Regex.Match (filename2, "\\(([0-9]+)\\)");
        int file2 = 0;
        if (m.Success) {
            file2 = int.Parse (m.Groups [1].Value); 
        }
        return file1 - file2;
}
于 2012-06-18T15:41:18.030 回答
2

请记住,默认情况下,Array.Sort(files) 将文件名排序为文本,而不是数字。尝试解析数字,然后按这些数字排序。

于 2012-06-18T15:00:05.383 回答
1

您可以使用 OrderBy 扩展,这里有更多详细信息http://msdn.microsoft.com/en-us/library/bb534966.aspx

这是一个简单的 lambda 表达式 t=> t 部分。如果需要,您可以在排序之前进行一些操作。

var files = Directory.GetFiles(inputImage, "*.*", SearchOption.TopDirectoryOnly).OrderBy(t => t);

如果您只想对数字进行排序,您可以进行一些巧妙的字符串替换,例如

.OrderBy(t => t.Replace("input", "").Replace("(", "").Replace(")","").Trim());
于 2012-06-18T15:03:12.307 回答
1

这个CustomSort可以提供帮助

List<string> list = new List<string>()
{
   "input (1).jpg","input (101).jpg", "input (11).jpg", "input (2).jpg"
};

var sortedList = list.CustomSort().ToList();

输出将是:

input (1).jpg
input (2).jpg
input (11).jpg
input (101).jpg

我将这里的代码复制

public static class MyExtensions
{
    public static IEnumerable<string> CustomSort(this IEnumerable<string> list)
    {
        int maxLen = list.Select(s => s.Length).Max();

        return list.Select(s => new
        {
            OrgStr = s,
            SortStr = Regex.Replace(s, @"(\d+)|(\D+)", m => m.Value.PadLeft(maxLen, char.IsDigit(m.Value[0]) ? ' ' : '\xffff'))
        })
        .OrderBy(x => x.SortStr)
        .Select(x => x.OrgStr);
    }
}
于 2012-06-18T16:29:04.633 回答
1

如果是我,我会创建一个字典对象并将第一个值存储为原始文件名,将第二个值存储为您需要按摩的自定义文件名。

因此,例如,字典对象看起来像这样:

input (1).jpg    |  input (001).jpg
input (2).jpg    |  input (002).jpg
input (101).jpg  |  input (101).jpg

然后您可以对第二个字段进行排序,但从字典对象的第一个字段中提取文件名。

于 2012-06-18T14:59:58.427 回答