【问题标题】:Get specific level of directory获取特定级别的目录
【发布时间】:2014-12-29 20:00:05
【问题描述】:

我想通过动态路径和用户名获取原始文件夹名称,并且没有Windows默认目录

例如,

 C:\Users\dynamic user\Desktop\History\2014-11-03\Spreadsheets\excel.xls
 C:\Users\dynamic user\Desktop\History\record.xls

在这种情况下,我希望它为 excel.xls 和 record.xls 返回“历史”。我尝试使用 GetFilename() 方法。但它只是返回

 Spreadsheets - excel.xls
 History      - record.xls

有可能实现吗?感谢您的帮助。

【问题讨论】:

    标签: c# directory subdirectory


    【解决方案1】:

    是的,就像documented of Path.GetFileName

    返回指定路径字符串的文件名和扩展名

    一种解决方案可以删除您的Desktop 路径并使用Path.DirectorySeparatorChar 字符拆分并获取第二个元素。

    例如;

    string path = @"C:\Users\dynamic user\Desktop\History\2014-11-03\Spreadsheets\excel.xls";
    var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
    
    path = path.Replace(desktop, "");
    var history = path.Split(Path.DirectorySeparatorChar)[1];
    Console.WriteLine(history); // History
    

    记住,Environment.SpecialFolder.Desktop 返回当前用户桌面信息。

    【讨论】:

    • 这假定路径从桌面开始并包含在单个文件夹中。
    • @cjb110 不,它没有。你曾经看过我的例子吗?它有\History\2014-11-03,这意味着除了Desktop 路径之外,这个字符串有两个内部文件夹。即使有两个以上的文件夹,我的解决方案也会起作用,因为它在拆分后获得第二个元素(第一个是空字符串,因为path\ character 开头)操作,在 OP 的情况下,它总是History .
    【解决方案2】:

    那么,如果我理解您想从一组路径中找到公共基本路径? 没有任何内置函数可以做到这一点,所以你回到字符串匹配和一些 LINQ 给出这个:

            static void Main(string[] args)
        {
            List<string> paths = new List<string>()
                {
                    @"C:\Users\dynamic user\Desktop\History\2014-11-03\Spreadsheets\excel.xls"
                    ,@"C:\Users\dynamic user\Desktop\History\record.xls"
                    ,@"C:\Users\dynamic user\Desktop\History\2014-11-23\Spreadsheets\excel.xls"
                    ,@"C:\Users\dynamic user\Desktop\History\2014-11-03\excel.xls"
                };
    
            Console.WriteLine("The common base path of:");
            paths.ForEach(f => Console.WriteLine(f));
            Console.WriteLine("is");
            Console.WriteLine(FindBasePath(paths));
    
            Console.ReadLine();
        }
    
        static string FindBasePath(List<string> paths)
        {
            string basePath = String.Empty;
    
            foreach (string path in paths)
            {
                string dirName = Path.GetDirectoryName(path);
    
                if (paths.All(f => Path.GetDirectoryName(f).Contains(dirName)))
                    return basePath = dirName;
            }
    
            return basePath;
        }
    

    忘记添加关于我们正在做什么的评论。基本上我们遍历每个路径,并获取目录的名称,然后如果 ALL 路径包含此字符串,则它必须是公共根目录。

    请注意,这将检查每条路径与其他所有路径...并且可以改进。

    你也可以用一个 LINQ 语句来做:

    paths.Select(f => Path.GetDirectoryName(f)
         .Select(f => paths.All(g => g.Contains(f)) ? f : "")
         .Where(f => !String.IsNullOrEmpty(f))
         .First()
    

    【讨论】:

      【解决方案3】:

      没有内置的方式来做你想做的事。以下代码应该可以解决问题:

          public static string GetFolderByLevel(this string path, string baseFolderName, int level)
          {
              if (path == null)
                  throw new ArgumentNullException("path");
      
              if (baseFolderName == null)
                  throw new ArgumentNullException("baseFolderName");
      
              var pathWithoutFile = Path.GetDirectoryName(path);
      
              var folders = pathWithoutFile.ToString().Split(Path.DirectorySeparatorChar);
              int baseFolderLevel = -1;
      
              for (int i = 0; i < folders.Length; ++i)
              {
                  if (string.Compare(folders[i], baseFolderName, true) == 0)
                  {
                      baseFolderLevel = i;
                      break;
                  }
              }
      
              if (baseFolderLevel == -1)
                  throw new ArgumentException(string.Format("Folder '{0}' could not be found in specified path: {1}", baseFolderName, path), "baseFolderName");
      
              int index = baseFolderLevel + level;
      
              if (-1 < index && index < folders.Length)
              {
                  return folders[index];
              }
              else
                  throw new ArgumentOutOfRangeException(string.Format("Specified level is out of range."));
          }
      

      现在你可以像这样使用它:

      string path = @"C:\Users\dynamic user\Desktop\History\Peter\record.xls";
      
      path.GetFolderByLevel("Desktop", -2); //returns "Users"
      path.GetFolderByLevel("History", 0); //returns "History"
      path.GetFolderByLevel("Desktop", 1); //returns "History"
      

      在你的情况下,如果我没记错的话,你正在寻找path.GetFolderByLevel("Desktop", 1);

      更新:我已经修改了之前的解决方案,以便您可以使用部分或完整路径指定 基本文件夹

      public static string GetFolderByLevel(this string path, string baseFolderPath, int level)
      {
          if (path == null)
              throw new ArgumentNullException("path");
      
          if (baseFolderPath == null)
              throw new ArgumentNullException("baseFolderName");
      
          var pathFolders = path.Split(new char[] {Path.DirectorySeparatorChar}, StringSplitOptions.RemoveEmptyEntries);
          var basePathFolders = baseFolderPath.Split(new char[] { Path.DirectorySeparatorChar }, StringSplitOptions.RemoveEmptyEntries);
      
          int baseFolderIndex = -1;
          int folderCounter = 0;
      
          for (int i = 0; i < pathFolders.Length; ++i)
          {
              if (string.Compare(pathFolders[i], basePathFolders[folderCounter], true) == 0)
              {
                  if (++folderCounter == basePathFolders.Length)
                  {
                      baseFolderIndex = i;
                      break;
                  }
              }
              else
              {
                  folderCounter = 0;
              }
          }
      
          if (baseFolderIndex < 0)
             throw new ArgumentException(string.Format("Folder '{0}' could not be found in specified path: {1}", baseFolderPath, path), "baseFolderName");
      
          int index = baseFolderIndex + level;
      
          if (-1 < index && index < pathFolders.Length)
          {
              return pathFolders[index];
          }
          else
              throw new ArgumentOutOfRangeException(string.Format("Specified level is out of range."));
      }
      

      现在你可以像这样使用它:path.GetFolderByLevel(Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), 1);

      另一个优点是在嵌套文件夹同名的情况下,您可以指定基本文件夹的唯一部分路径,以确保方法选择正确的路径。

      【讨论】:

      • 聪明,但我认为OP不会知道他需要的级别数。
      • @cjb110 是的,他确实这样做了,除非我误解了 OP 的问题。
      • 啊,你上路了:) 我下楼了,以为他有一组未知的路径,想找到共同的基本路径。
      • 没错,层数是动态的
      【解决方案4】:

      或者这个:

       var dir_path = Path.GetDirectoryName(@"C:\your\path\with\file.ext");
       var dir_name = new DirectoryInfo(dir_path).Name;
      

      【讨论】:

      • 不,对于 \History\2014-11-03,这将返回 2014-11-03 部分而不是 History
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-29
      • 1970-01-01
      相关资源
      最近更新 更多