C#中调用Path.GetFileNameWithoutExtension解析编号失败

问题描述

  帮单位同事编写从其它系统接收零件信息的模块,其中一个属性是零件编号,零件编号是有编号规则的,但是测试过程中发现有些编号填写不规范,编号会以文件名的形式传过来,形式如XXX-XX-XXXX.dwg等。于是在接收零件信息,保存零件编号时,对零件编号做了处理,如果带后缀名,则去掉后缀名,只保留前面的名称。
  在实际使用过程中,用户偶尔会反馈,接收过来的零件编号不对,只有一部分内容,还需要用户手动补全编号内容。具体的问题如零件编号为XXX-XX-XXXX/F2,则接收后只显示为F2。

原因分析

  通过查看代码,发现接收零件信息并保存零件编号时对其进行了处理,如果包含文件后缀名,则去掉文件后缀名,只保留前面的内容。当时为了省事儿,直接调用的System.IO命名空间中的Path.GetFileNameWithoutExtension解析编号,就是调用这个函数出的问题。
  MSDN中给的示例如下,通过示例及示例的输出可以看到,GetFileNameWithoutExtension函数返回不带文件后缀名的文件名称,如果文件名带路径,也会把路径去掉。

string fileName = @"C:\mydir\myfile.ext";
string path = @"C:\mydir\";
string result;

result = Path.GetFileNameWithoutExtension(fileName);
Console.WriteLine("GetFileNameWithoutExtension('{0}') returns '{1}'", 
    fileName, result);

result = Path.GetFileName(path);
Console.WriteLine("GetFileName('{0}') returns '{1}'", 
    path, result);

// This code produces output similar to the following:
//
// GetFileNameWithoutExtension('C:\mydir\myfile.ext') returns 'myfile'
// GetFileName('C:\mydir\') returns ''

  此时,问题的原因已经比较清晰,当时做功能测试时仅是测了比较简单的编号形式XXX-XX-XXXX,没有测试XXX-XX-XXXX/F2形式的编号,GetFileNameWithoutExtension解析XXX-XX-XXXX/F2时,估计是把它当成相对路径来解析了,为了验证想法,找到GetFileNameWithoutExtension的源码看看,代码如下:

        // Returns the name and extension parts of the given path. The resulting
        // string contains the characters of path that follow the last
        // backslash ("\"), slash ("/"), or colon (":") character in 
        // path. The resulting string is the entire path if path 
        // contains no backslash after removing trailing slashes, slash, or colon characters. The resulting 
        // string is null if path is null.
        //
        [Pure]
        public static String GetFileName(String path) {
          if (path != null) {
                CheckInvalidPathChars(path);
    
                int length = path.Length;
                for (int i = length; --i >= 0;) {
                    char ch = path[i];
                    if (ch == DirectorySeparatorChar || ch == AltDirectorySeparatorChar || ch == VolumeSeparatorChar)
                        return path.Substring(i + 1, length - i - 1);

                }
            }
            return path;
        }

        [Pure]
        public static String GetFileNameWithoutExtension(String path) {
            path = GetFileName(path);
            if (path != null)
            {
                int i;
                if ((i=path.LastIndexOf('.')) == -1)
                    return path; // No path extension found
                else
                    return path.Substring(0,i);
            }
            return null;
         }

  通过上述代码逻辑可以看到,GetFileNameWithoutExtension函数传入文件名后,首先调用GetFileName函数获取文件名称,GetFileName的函数逻辑是从后往前找‘\’、’/’、’:‘字符,找到就去该字符后面的内容作为文件名称返回。我之前程序中的问题就是因此产生的,把’/'之前的部分编号当成路径给去掉了。

解决方案

  问题找到了,解决方法就比较简单,直接把GetFileNameWithoutExtension中的部分代码复制过来,只检查编号中是否有’.’,有的话就取前面的内容,代码如下:

            if (partNo != null)
            {
                int i;
                if ((i=partNo .LastIndexOf('.')) == -1)
                    return partNo ; // No path extension found
                else
                    return partNo .Substring(0,i);
            } 

  问题解决的比较简容易,但是之前写代码时没有测试完整才是最大的问题,以后还是不能犯懒才行。

参考文献:
[1]https://docs.microsoft.com/zh-cn/dotnet/api/system.io.path.getfilenamewithoutextension?redirectedfrom=MSDN&view=netframework-4.8
[2]https://referencesource.microsoft.com/,可以在这里免费下.net framework的源码。

发布了157 篇原创文章 · 获赞 102 · 访问量 45万+

猜你喜欢

转载自blog.csdn.net/gc_2299/article/details/104025876
今日推荐