286

我在 WPF C# 中编程。我有例如以下路径:

C:\Program Files\hello.txt

我想从中提取hello

该路径是string从数据库中检索的。目前我正在使用以下代码分割路径'\',然后再次分割'.'

string path = "C:\\Program Files\\hello.txt";
string[] pathArr = path.Split('\\');
string[] fileArr = pathArr.Last().Split('.');
string fileName = fileArr.Last().ToString();

它有效,但我相信应该有更短和更智能的解决方案。任何的想法?

4

10 回答 10

544

Path.GetFileName

返回由只读字符范围表示的文件路径的文件名和扩展名。


Path.GetFileNameWithoutExtension

返回不带文件路径扩展名的文件名,该文件路径由只读字符范围表示。


Path课堂很棒。

于 2011-08-03T02:47:57.870 回答
95

尝试

fileName = Path.GetFileName (path);

http://msdn.microsoft.com/de-de/library/system.io.path.getfilename.aspx

于 2011-08-03T02:48:58.380 回答
31

尝试

System.IO.Path.GetFileNameWithoutExtension(path); 

演示

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 ''

https://msdn.microsoft.com/en-gb/library/system.io.path.getfilenamewithoutextension%28v=vs.80%29.aspx

于 2011-08-03T02:50:00.023 回答
29

您可以按如下方式使用Path API:

 var filenNme = Path.GetFileNameWithoutExtension([File Path]);

更多信息:Path.GetFileNameWithoutExtension

于 2011-08-03T02:48:44.527 回答
19
var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path);

Path.GetFileNameWithoutExtension

于 2011-08-03T02:50:22.870 回答
11

试试这个:

string fileName = Path.GetFileNameWithoutExtension(@"C:\Program Files\hello.txt");

这将为文件名返回“hello”。

于 2011-08-03T02:49:49.840 回答
10
string Location = "C:\\Program Files\\hello.txt";

string FileName = Location.Substring(Location.LastIndexOf('\\') +
    1);
于 2015-08-27T10:23:36.863 回答
5

首先,问题中的代码不会产生所描述的输出。它提取文件扩展名( "txt") 而不是文件基名( "hello")。要做到这一点,最后一行应该调用First(),而不是Last()像这样......

static string GetFileBaseNameUsingSplit(string path)
{
    string[] pathArr = path.Split('\\');
    string[] fileArr = pathArr.Last().Split('.');
    string fileBaseName = fileArr.First().ToString();

    return fileBaseName;
}

进行了更改后,就改进此代码而言,要考虑的一件事是它产生的垃圾量:

  • A中的每个路径段string[]包含一个stringpath
  • A中的最后一个路径段中的每个string[]至少包含一个string.path

因此,从示例路径中提取基本文件名"C:\Program Files\hello.txt"应生成(临时)objects "C:""Program Files""hello.txt""hello""txt"、 astring[3]和 a string[2]。如果在大量路径上调用该方法,这可能很重要。为了改进这一点,我们可以搜索path自己来定位基本名称的起点和终点,并使用它们来创建一个新的string......

static string GetFileBaseNameUsingSubstringUnsafe(string path)
{
    // Fails on paths with no file extension - DO NOT USE!!
    int startIndex = path.LastIndexOf('\\') + 1;
    int endIndex = path.IndexOf('.', startIndex);
    string fileBaseName = path.Substring(startIndex, endIndex - startIndex);

    return fileBaseName;
}

这是使用最后一个字符的索引\作为基本名称的开始,并从那里寻找第一个.用作基本名称结束后字符的索引。这比原始代码短吗?不完全的。这是一个“更智能”的解决方案吗?我认同。至少,如果不是因为……

从评论中可以看出,前面的方法是有问题的。\尽管假设所有路径都以带有扩展名的文件名结尾,但如果路径以(即目录路径)结尾或在最后一段中不包含扩展名,它将引发异常。为了解决这个问题,我们需要添加一个额外的检查来说明什么时候endIndex-1(即.未找到)......

static string GetFileBaseNameUsingSubstring(string path)
{
    int startIndex = path.LastIndexOf('\\') + 1;
    int endIndex = path.IndexOf('.', startIndex);
    int length = (endIndex >= 0 ? endIndex : path.Length) - startIndex;
    string fileBaseName = path.Substring(startIndex, length);

    return fileBaseName;
}

现在这个版本远不比原来的版本短,但它更有效并且(现在)也正确。

至于实现此功能的 .NET 方法,许多其他答案建议使用Path.GetFileNameWithoutExtension(),这是一个明显、简单的解决方案,但不会产生与问题中的代码相同的结果。GetFileBaseNameUsingSplit()Path.GetFileNameWithoutExtension()(下 )之间有一个微妙但重要的区别GetFileBaseNameUsingPath():前者提取第一个 .之前的所有内容,后者提取最后一个 .之前的所有内容。这path对问题中的示例没有什么影响,但是看一下这张表,比较了上述四种方法在使用各种路径调用时的结果......

描述 方法 小路 结果
单扩展 GetFileBaseNameUsingSplit() "C:\Program Files\hello.txt" "hello"
单扩展 GetFileBaseNameUsingPath() "C:\Program Files\hello.txt" "hello"
单扩展 GetFileBaseNameUsingSubstringUnsafe() "C:\Program Files\hello.txt" "hello"
单扩展 GetFileBaseNameUsingSubstring() "C:\Program Files\hello.txt" "hello"




双扩展 GetFileBaseNameUsingSplit() "C:\Program Files\hello.txt.ext" "hello"
双扩展 GetFileBaseNameUsingPath() "C:\Program Files\hello.txt.ext" "hello.txt"
双扩展 GetFileBaseNameUsingSubstringUnsafe() "C:\Program Files\hello.txt.ext" "hello"
双扩展 GetFileBaseNameUsingSubstring() "C:\Program Files\hello.txt.ext" "hello"




无扩展 GetFileBaseNameUsingSplit() "C:\Program Files\hello" "hello"
无扩展 GetFileBaseNameUsingPath() "C:\Program Files\hello" "hello"
无扩展 GetFileBaseNameUsingSubstringUnsafe() "C:\Program Files\hello" 例外:长度不能小于零。(参数“长度”)
无扩展 GetFileBaseNameUsingSubstring() "C:\Program Files\hello" "hello"




领先时期 GetFileBaseNameUsingSplit() "C:\Program Files\.hello.txt" ""
领先时期 GetFileBaseNameUsingPath() "C:\Program Files\.hello.txt" ".hello"
领先时期 GetFileBaseNameUsingSubstringUnsafe() "C:\Program Files\.hello.txt" ""
领先时期 GetFileBaseNameUsingSubstring() "C:\Program Files\.hello.txt" ""




尾随期 GetFileBaseNameUsingSplit() "C:\Program Files\hello.txt." "hello"
尾随期 GetFileBaseNameUsingPath() "C:\Program Files\hello.txt." "hello.txt"
尾随期 GetFileBaseNameUsingSubstringUnsafe() "C:\Program Files\hello.txt." "hello"
尾随期 GetFileBaseNameUsingSubstring() "C:\Program Files\hello.txt." "hello"




目录路径 GetFileBaseNameUsingSplit() "C:\Program Files\" ""
目录路径 GetFileBaseNameUsingPath() "C:\Program Files\" ""
目录路径 GetFileBaseNameUsingSubstringUnsafe() "C:\Program Files\" 例外:长度不能小于零。(参数“长度”)
目录路径 GetFileBaseNameUsingSubstring() "C:\Program Files\" ""




当前文件路径 GetFileBaseNameUsingSplit() "hello.txt" "hello"
当前文件路径 GetFileBaseNameUsingPath() "hello.txt" "hello"
当前文件路径 GetFileBaseNameUsingSubstringUnsafe() "hello.txt" "hello"
当前文件路径 GetFileBaseNameUsingSubstring() "hello.txt" "hello"




父文件路径 GetFileBaseNameUsingSplit() "..\hello.txt" "hello"
父文件路径 GetFileBaseNameUsingPath() "..\hello.txt" "hello"
父文件路径 GetFileBaseNameUsingSubstringUnsafe() "..\hello.txt" "hello"
父文件路径 GetFileBaseNameUsingSubstring() "..\hello.txt" "hello"




父目录路径 GetFileBaseNameUsingSplit() ".." ""
父目录路径 GetFileBaseNameUsingPath() ".." "."
父目录路径 GetFileBaseNameUsingSubstringUnsafe() ".." ""
父目录路径 GetFileBaseNameUsingSubstring() ".." ""

...并且您会看到,Path.GetFileNameWithoutExtension()当传递文件名具有双扩展名或前导和/或尾随的路径时,会产生不同的结果.。您可以使用以下代码自己尝试...

using System;
using System.IO;
using System.Linq;
using System.Reflection;

namespace SO6921105
{
    internal class PathExtractionResult
    {
        public string Description { get; set; }
        public string Method { get; set; }
        public string Path { get; set; }
        public string Result { get; set; }
    }

    public static class Program
    {
        private static string GetFileBaseNameUsingSplit(string path)
        {
            string[] pathArr = path.Split('\\');
            string[] fileArr = pathArr.Last().Split('.');
            string fileBaseName = fileArr.First().ToString();

            return fileBaseName;
        }

        private static string GetFileBaseNameUsingPath(string path)
        {
            return Path.GetFileNameWithoutExtension(path);
        }

        private static string GetFileBaseNameUsingSubstringUnsafe(string path)
        {
            // Fails on paths with no file extension - DO NOT USE!!
            int startIndex = path.LastIndexOf('\\') + 1;
            int endIndex = path.IndexOf('.', startIndex);
            string fileBaseName = path.Substring(startIndex, endIndex - startIndex);

            return fileBaseName;
        }

        private static string GetFileBaseNameUsingSubstring(string path)
        {
            int startIndex = path.LastIndexOf('\\') + 1;
            int endIndex = path.IndexOf('.', startIndex);
            int length = (endIndex >= 0 ? endIndex : path.Length) - startIndex;
            string fileBaseName = path.Substring(startIndex, length);

            return fileBaseName;
        }

        public static void Main()
        {
            MethodInfo[] testMethods = typeof(Program).GetMethods(BindingFlags.NonPublic | BindingFlags.Static)
                .Where(method => method.Name.StartsWith("GetFileBaseName"))
                .ToArray();
            var inputs = new[] {
                new { Description = "Single extension",      Path = @"C:\Program Files\hello.txt"     },
                new { Description = "Double extension",      Path = @"C:\Program Files\hello.txt.ext" },
                new { Description = "No extension",          Path = @"C:\Program Files\hello"         },
                new { Description = "Leading period",        Path = @"C:\Program Files\.hello.txt"    },
                new { Description = "Trailing period",       Path = @"C:\Program Files\hello.txt."    },
                new { Description = "Directory path",        Path = @"C:\Program Files\"              },
                new { Description = "Current file path",     Path = "hello.txt"                       },
                new { Description = "Parent file path",      Path = @"..\hello.txt"                   },
                new { Description = "Parent directory path", Path = ".."                              }
            };
            PathExtractionResult[] results = inputs
                .SelectMany(
                    input => testMethods.Select(
                        method => {
                            string result;

                            try
                            {
                                string returnValue = (string) method.Invoke(null, new object[] { input.Path });

                                result = $"\"{returnValue}\"";
                            }
                            catch (Exception ex)
                            {
                                if (ex is TargetInvocationException)
                                    ex = ex.InnerException;
                                result = $"EXCEPTION: {ex.Message}";
                            }

                            return new PathExtractionResult() {
                                Description = input.Description,
                                Method = $"{method.Name}()",
                                Path = $"\"{input.Path}\"",
                                Result = result
                            };
                        }
                    )
                ).ToArray();
            const int ColumnPadding = 2;
            ResultWriter writer = new ResultWriter(Console.Out) {
                DescriptionColumnWidth = results.Max(output => output.Description.Length) + ColumnPadding,
                MethodColumnWidth = results.Max(output => output.Method.Length) + ColumnPadding,
                PathColumnWidth = results.Max(output => output.Path.Length) + ColumnPadding,
                ResultColumnWidth = results.Max(output => output.Result.Length) + ColumnPadding,
                ItemLeftPadding = " ",
                ItemRightPadding = " "
            };
            PathExtractionResult header = new PathExtractionResult() {
                Description = nameof(PathExtractionResult.Description),
                Method = nameof(PathExtractionResult.Method),
                Path = nameof(PathExtractionResult.Path),
                Result = nameof(PathExtractionResult.Result)
            };

            writer.WriteResult(header);
            writer.WriteDivider();
            foreach (IGrouping<string, PathExtractionResult> resultGroup in results.GroupBy(result => result.Description))
            {
                foreach (PathExtractionResult result in resultGroup)
                    writer.WriteResult(result);
                writer.WriteDivider();
            }
        }
    }

    internal class ResultWriter
    {
        private const char DividerChar = '-';
        private const char SeparatorChar = '|';

        private TextWriter Writer { get; }

        public ResultWriter(TextWriter writer)
        {
            Writer = writer ?? throw new ArgumentNullException(nameof(writer));
        }

        public int DescriptionColumnWidth { get; set; }

        public int MethodColumnWidth { get; set; }

        public int PathColumnWidth { get; set; }

        public int ResultColumnWidth { get; set; }

        public string ItemLeftPadding { get; set; }

        public string ItemRightPadding { get; set; }

        public void WriteResult(PathExtractionResult result)
        {
            WriteLine(
                $"{ItemLeftPadding}{result.Description}{ItemRightPadding}",
                $"{ItemLeftPadding}{result.Method}{ItemRightPadding}",
                $"{ItemLeftPadding}{result.Path}{ItemRightPadding}",
                $"{ItemLeftPadding}{result.Result}{ItemRightPadding}"
            );
        }

        public void WriteDivider()
        {
            WriteLine(
                new string(DividerChar, DescriptionColumnWidth),
                new string(DividerChar, MethodColumnWidth),
                new string(DividerChar, PathColumnWidth),
                new string(DividerChar, ResultColumnWidth)
            );
        }

        private void WriteLine(string description, string method, string path, string result)
        {
            Writer.Write(SeparatorChar);
            Writer.Write(description.PadRight(DescriptionColumnWidth));
            Writer.Write(SeparatorChar);
            Writer.Write(method.PadRight(MethodColumnWidth));
            Writer.Write(SeparatorChar);
            Writer.Write(path.PadRight(PathColumnWidth));
            Writer.Write(SeparatorChar);
            Writer.Write(result.PadRight(ResultColumnWidth));
            Writer.WriteLine(SeparatorChar);
        }
    }
}

TL; DR 问题中的代码在某些极端情况下的表现并不像许多人所期望的那样。如果您要编写自己的路径操作代码,请务必考虑...

  • ...您如何定义“不带扩展名的文件名”(是第一个之前的.所有内容还是最后一个之前的所有内容.?)
  • ...具有多个扩展名的文件
  • ...没有扩展名的文件
  • ...带有前导的文件.
  • ...带有尾随的文件.(可能不会在 Windows 上遇到,但它们是可能的
  • ...具有“扩展名”或以其他方式包含.
  • ...以 a 结尾的路径\
  • ...相对路径

并非所有文件路径都遵循通常的公式X:\Directory\File.ext

于 2020-02-05T04:03:51.250 回答
1
string filepath = "C:\\Program Files\\example.txt";
FileVersionInfo myFileVersionInfo = FileVersionInfo.GetVersionInfo(filepath);
FileInfo fi = new FileInfo(filepath);
Console.WriteLine(fi.Name);

//input to the "fi" is a full path to the file from "filepath"
//This code will return the fileName from the given path

//output
//example.txt
于 2019-01-31T07:08:44.853 回答
-1
Namespace: using System.IO;  
 //use this to get file name dynamically 
 string filelocation = Properties.Settings.Default.Filelocation;
//use this to get file name statically 
//string filelocation = @"D:\FileDirectory\";
string[] filesname = Directory.GetFiles(filelocation); //for multiple files
    

如果您要动态获取文件名,则在 App.config 文件中的路径配置 -

    <userSettings>
        <ConsoleApplication13.Properties.Settings>
          <setting name="Filelocation" serializeAs="String">
            <value>D:\\DeleteFileTest</value>
          </setting>
              </ConsoleApplication13.Properties.Settings>
      </userSettings>
于 2018-01-10T12:25:59.723 回答