0

在我的帖子底部解决。

或者更具体地说:

我有一堆 FileInfo 对象(我需要 FileInfo 对象来排除隐藏、系统和重新分析点文件)。

我需要根据 FileInfo.FullName 自然地对 FileInfo[] 进行排序。所以 FILE_10.ext 应该在 FILE_2.ext 之后。幸运的是 FileInfo[] 只包含一个扩展名的文件。

我已经实现了一个比较器:

/// <summary>
/// Compares FileInfo objects based on the files full path.
/// This comparer is flawed in that it will only work correctly
/// on files with the same extension.
/// Though that could easily be fixed.
/// </summary>
private class FileInfoSorter : IComparer
{

    int IComparer.Compare(Object x, Object y)
    {
        FileInfo _x = x as FileInfo;
        FileInfo _y = y as FileInfo;

        // FYI: 
        //ExprFileVersion = new Regex("(.*)_([0-9]+)\\.[^\\.]+$", RegexOptions.Compiled);
        Match m1 = RegExps.ExprFileVersion.Match(_x.FullName);
        Match m2 = RegExps.ExprFileVersion.Match(_y.FullName);
        if (m1.Success && m2.Success) // we have versioned files
        {
            int n1;
            int n2;
            try
            {
                n1 = int.Parse(m1.Groups[2].Value);
            }
            catch (OverflowException ex)
            {
                // Don't know if this works.
                ex.Data["File"] = _x.FullName;
                throw;
            }

            try
            {
                n2 = int.Parse(m2.Groups[2].Value);
            }
            catch (OverflowException ex)
            {
                // Don't know if this works.
                ex.Data["File"] = _y.FullName;
                throw;
            }


            string s1 = m1.Groups[1].Value;
            string s2 = m2.Groups[1].Value;

            if (s1.Equals(s2))
            {
                return n1.CompareTo(n2); // compare numbers naturally. E.g. 11 > 6                        
            }
            else // not the same base file name. So the version does not matter.
            {
                return ((new CaseInsensitiveComparer()).Compare(_x.FullName, _y.FullName));
            }
        }
        else // not versioned
        {
            return ((new CaseInsensitiveComparer()).Compare(_x.FullName, _y.FullName));
        }
    }


}

现在问题出现了,int.Parse 抛出了一个溢出异常,我无法在正确的位置捕获它(由于某种原因,它再次出现在 return 语句的行上,我无法在更上一层智能地处理它,因为它永远不会到达那里)。

问题是:这种事情是否有预先实现的比较器?异常出现在有趣的地方的原因可能是什么?

调用代码:

    IComparer fiComparer = new FileInfoSorter();

        try
        {
            Array.Sort(filesOfExtInfo, fiComparer);
        }
        catch (OverflowException ex)
        {
            // Do not know yet if I can use ex.Data in this way.
            WriteStatusLineAsync("Error: Encountered too large a version number on file: " + ex.Data["File"]);
        }

EDIT1: Int.Parse 在遇到太大的数字时抛出 OverflowException。它不应该经常发生,但我希望它被覆盖。

EDIT2:我最终调整了自己的比较器。离开了 int.Parse 并且只是用零填充以进行比较。代码在这里:

    public class FileInfoSorter : IComparer
    {

        int IComparer.Compare(Object x, Object y)
        {
            FileInfo _x = x as FileInfo;
            FileInfo _y = y as FileInfo;

            Match m1 = RegExps.ExprFileVersion.Match(_x.FullName);
            Match m2 = RegExps.ExprFileVersion.Match(_y.FullName);
            if (m1.Success && m2.Success) // we have versioned files
            {

                string n1;
                string n2;
                n1 = m1.Groups[2].Value;
                n2 = m2.Groups[2].Value;

                string s1 = m1.Groups[1].Value;
                string s2 = m2.Groups[1].Value;

                int max = Math.Max(n1.Length, n2.Length);

                n1 = n1.PadLeft(max, '0');
                n2 = n2.PadLeft(max, '0');

                if (s1.Equals(s2)) // we have to compare the version
                    // which is now left-padded with 0s.
                {
                    return ((new CaseInsensitiveComparer()).Compare(n1, n2)); 
                }
                else // not the same base file name. So the version does not matter.
                {
                    return ((new CaseInsensitiveComparer()).Compare(_x.FullName, _y.FullName));
                }
            }
            else // not versioned
            {
                return ((new CaseInsensitiveComparer()).Compare(_x.FullName, _y.FullName));
            }
        }
    }
4

1 回答 1

1

就在这里。这个问题已经在这里回答了。您基本上想通过 P/Invoke 层调用StrCmpLogicalW函数。有关详细信息,请参阅原始答案:

C#中的自然排序顺序

于 2009-01-08T20:29:28.727 回答