Gibt es bei einem Dateisystempfad eine kürzere Möglichkeit, den Dateinamen ohne seine Erweiterung zu extrahieren?

260

Ich programmiere in WPF C #. Ich habe zB folgenden Weg:

C:\Program Files\hello.txt

und ich möchte daraus extrahieren hello.

Der Pfad wird stringaus einer Datenbank abgerufen. Derzeit verwende ich den folgenden Code, um den Pfad zu teilen '\'und dann erneut zu teilen '.':

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

Es funktioniert, aber ich glaube, es sollte eine kürzere und intelligentere Lösung dafür geben. Irgendeine Idee?

KMC
quelle
Path.GetFileName("C:\\dev\\some\\path\\to\\file.cs")Gibt in meinem System dieselbe Zeichenfolge zurück und konvertiert sie aus irgendeinem Grund nicht in "file.cs". Wenn ich meinen Code in einen Online-Compiler (wie rextester.com ) kopiere / einfüge , funktioniert es ...?
21.

Antworten:

29

Versuchen

System.IO.Path.GetFileNameWithoutExtension(path); 

Demo

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

Montag
quelle
Es scheint, dass Path.GetFileNameWithoutExtension () nicht mit einer Dateierweiterung> 3 Zeichen funktioniert.
Nolmë Informatique
26

Sie können die Pfad- API wie folgt verwenden:

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

Weitere Informationen: Path.GetFileNameWithoutExtension

Peyman
quelle
11

Versuche dies:

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

Dies gibt "Hallo" für Dateiname zurück.

Tim
quelle
9
string Location = "C:\\Program Files\\hello.txt";

string FileName = Location.Substring(Location.LastIndexOf('\\') +
    1);
Raman
quelle
1
+1, da dies in dem Fall hilfreich sein kann, in dem dies als Sicherung funktioniert, bei der der Dateiname ungültige Zeichen [<,> usw. in Path.GetInvalidChars ()] enthält.
Bhuvin
Dies ist sehr nützlich, wenn Sie mit Pfaden auf UNIX-FTP-Servern arbeiten.
s952163
6

Versuche dies,

string FilePath=@"C:\mydir\myfile.ext";
string Result=Path.GetFileName(FilePath);//With Extension
string Result=Path.GetFileNameWithoutExtension(FilePath);//Without Extension
Sumanth
quelle
2
Sie haben genau die gleichen Methoden angewendet, die in der Antwort mit der höchsten Bewertung erwähnt wurden.
CodeCaster
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
Ganesh Kalidas
quelle
Ich bin überrascht, dass FileVersionInfodies für Dateien verwendet werden kann, die keine Versionsinformationen enthalten. Beachten Sie, dass GetVersionInfo()dies nur für Pfade verwendet werden kann, die auf eine bereits vorhandene Datei verweisen. Während jede Klasse verwendet werden kann, um den Dateinamen abzurufen, wurde in der Frage auch gefragt, ob die Erweiterung ebenfalls entfernt werden soll.
Speck
1

Erstens erzeugt der Code in der Frage nicht die beschriebene Ausgabe. Es extrahiert die Datei - Erweiterung ( "txt") und nicht die Datei Basisnamen ( "hello"). Zu tun , dass die letzte Zeile nennen sollte First(), nicht Last(), wie dieser ...

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

    return fileBaseName;
}

Nachdem Sie diese Änderung vorgenommen haben, sollten Sie bei der Verbesserung dieses Codes über die Menge an Müll nachdenken, die er erzeugt:

  • A string[]enthält eine stringfür jedes Pfadsegment inpath
  • A , string[]enthaltend mindestens ein stringfür jedes .in dem letzten Pfadsegment inpath

Daher Extrahieren der Basisdateinamen von dem Probenweg "C:\Program Files\hello.txt"sollte erzeugt die (temporäre) objects "C:", "Program Files", "hello.txt", "hello", "txt", a string[3], und a string[2]. Dies kann von Bedeutung sein, wenn die Methode auf einer großen Anzahl von Pfaden aufgerufen wird. Um dies zu verbessern, können wir pathuns selbst suchen , um den Start- und Endpunkt des Basisnamens zu finden und diese zu verwenden, um einen neuen 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;
}

Hierbei wird der Index des Zeichens nach dem letzten \als Anfang des Basisnamens verwendet und von dort aus nach dem ersten gesucht, .der nach dem Ende des Basisnamens als Index des Zeichens verwendet werden soll. Ist das kürzer als der ursprüngliche Code? Nicht ganz. Ist es eine "intelligentere" Lösung? Ich glaube schon. Zumindest wäre es ohne die Tatsache, dass ...

Wie Sie dem Kommentar entnehmen können, ist die vorherige Methode problematisch. Obwohl dies funktioniert, wenn Sie davon ausgehen, dass alle Pfade mit einem Dateinamen mit einer Erweiterung enden, wird eine Ausnahme ausgelöst, wenn der Pfad mit \(dh einem Verzeichnispfad) endet oder auf andere Weise keine Erweiterung im letzten Segment enthält. Um dies zu beheben, müssen wir einen zusätzlichen Scheck - Konto für hinzufügen , wenn endIndexist -1(dh .nicht gefunden wird ) ...

static string GetFileBaseNameUsingSubstringSafe(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;
}

Jetzt ist diese Version bei weitem nicht kürzer als das Original, aber sie ist effizienter und (jetzt) ​​auch korrekt.

In Bezug auf .NET-Methoden, die diese Funktionalität implementieren, schlagen viele andere Antworten die Verwendung vor. Dies Path.GetFileNameWithoutExtension()ist eine offensichtliche, einfache Lösung, führt jedoch nicht zu den gleichen Ergebnissen wie der Code in der Frage. Es gibt einen subtilen, aber wichtigen Unterschied zwischen GetFileBaseNameUsingSplit()und Path.GetFileNameWithoutExtension()( GetFileBaseNameUsingPath()unten): Ersteres extrahiert alles vor dem ersten . und Letzteres extrahiert alles vor dem letzten . . Dies macht für die Stichprobe pathin der Frage keinen Unterschied , aber sehen Sie sich diese Tabelle an, in der die Ergebnisse der oben genannten vier Methoden verglichen werden, wenn sie mit verschiedenen Pfaden aufgerufen werden ...

| Description           | Method                                | Path                             | Result                                                           |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| Single extension      | GetFileBaseNameUsingSplit()           | "C:\Program Files\hello.txt"     | "hello"                                                          |
| Single extension      | GetFileBaseNameUsingPath()            | "C:\Program Files\hello.txt"     | "hello"                                                          |
| Single extension      | GetFileBaseNameUsingSubstringUnsafe() | "C:\Program Files\hello.txt"     | "hello"                                                          |
| Single extension      | GetFileBaseNameUsingSubstringSafe()   | "C:\Program Files\hello.txt"     | "hello"                                                          |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| Double extension      | GetFileBaseNameUsingSplit()           | "C:\Program Files\hello.txt.ext" | "hello"                                                          |
| Double extension      | GetFileBaseNameUsingPath()            | "C:\Program Files\hello.txt.ext" | "hello.txt"                                                      |
| Double extension      | GetFileBaseNameUsingSubstringUnsafe() | "C:\Program Files\hello.txt.ext" | "hello"                                                          |
| Double extension      | GetFileBaseNameUsingSubstringSafe()   | "C:\Program Files\hello.txt.ext" | "hello"                                                          |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| No extension          | GetFileBaseNameUsingSplit()           | "C:\Program Files\hello"         | "hello"                                                          |
| No extension          | GetFileBaseNameUsingPath()            | "C:\Program Files\hello"         | "hello"                                                          |
| No extension          | GetFileBaseNameUsingSubstringUnsafe() | "C:\Program Files\hello"         | EXCEPTION: Length cannot be less than zero. (Parameter 'length') |
| No extension          | GetFileBaseNameUsingSubstringSafe()   | "C:\Program Files\hello"         | "hello"                                                          |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| Leading period        | GetFileBaseNameUsingSplit()           | "C:\Program Files\.hello.txt"    | ""                                                               |
| Leading period        | GetFileBaseNameUsingPath()            | "C:\Program Files\.hello.txt"    | ".hello"                                                         |
| Leading period        | GetFileBaseNameUsingSubstringUnsafe() | "C:\Program Files\.hello.txt"    | ""                                                               |
| Leading period        | GetFileBaseNameUsingSubstringSafe()   | "C:\Program Files\.hello.txt"    | ""                                                               |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| Trailing period       | GetFileBaseNameUsingSplit()           | "C:\Program Files\hello.txt."    | "hello"                                                          |
| Trailing period       | GetFileBaseNameUsingPath()            | "C:\Program Files\hello.txt."    | "hello.txt"                                                      |
| Trailing period       | GetFileBaseNameUsingSubstringUnsafe() | "C:\Program Files\hello.txt."    | "hello"                                                          |
| Trailing period       | GetFileBaseNameUsingSubstringSafe()   | "C:\Program Files\hello.txt."    | "hello"                                                          |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| Directory path        | GetFileBaseNameUsingSplit()           | "C:\Program Files\"              | ""                                                               |
| Directory path        | GetFileBaseNameUsingPath()            | "C:\Program Files\"              | ""                                                               |
| Directory path        | GetFileBaseNameUsingSubstringUnsafe() | "C:\Program Files\"              | EXCEPTION: Length cannot be less than zero. (Parameter 'length') |
| Directory path        | GetFileBaseNameUsingSubstringSafe()   | "C:\Program Files\"              | ""                                                               |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| Current file path     | GetFileBaseNameUsingSplit()           | "hello.txt"                      | "hello"                                                          |
| Current file path     | GetFileBaseNameUsingPath()            | "hello.txt"                      | "hello"                                                          |
| Current file path     | GetFileBaseNameUsingSubstringUnsafe() | "hello.txt"                      | "hello"                                                          |
| Current file path     | GetFileBaseNameUsingSubstringSafe()   | "hello.txt"                      | "hello"                                                          |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| Parent file path      | GetFileBaseNameUsingSplit()           | "..\hello.txt"                   | "hello"                                                          |
| Parent file path      | GetFileBaseNameUsingPath()            | "..\hello.txt"                   | "hello"                                                          |
| Parent file path      | GetFileBaseNameUsingSubstringUnsafe() | "..\hello.txt"                   | "hello"                                                          |
| Parent file path      | GetFileBaseNameUsingSubstringSafe()   | "..\hello.txt"                   | "hello"                                                          |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|
| Parent directory path | GetFileBaseNameUsingSplit()           | ".."                             | ""                                                               |
| Parent directory path | GetFileBaseNameUsingPath()            | ".."                             | "."                                                              |
| Parent directory path | GetFileBaseNameUsingSubstringUnsafe() | ".."                             | ""                                                               |
| Parent directory path | GetFileBaseNameUsingSubstringSafe()   | ".."                             | ""                                                               |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|

... und Sie werden sehen, dass Path.GetFileNameWithoutExtension()unterschiedliche Ergebnisse erzielt werden, wenn ein Pfad übergeben wird, in dem der Dateiname eine doppelte Erweiterung oder eine führende und / oder nachfolgende hat .. Sie können es selbst mit dem folgenden Code versuchen ...

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 GetFileBaseNameUsingSubstringSafe(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 Der Code in der Frage verhält sich in einigen Eckfällen nicht so, wie es viele zu erwarten scheinen . Wenn Sie Ihren eigenen Pfadmanipulationscode schreiben möchten, müssen Sie Folgendes berücksichtigen ...

  • ... wie Sie eine "Erweiterung" definieren (ist es alles vor dem ersten .oder alles vor dem letzten .?)
  • ... Dateien mit mehreren Erweiterungen
  • ... Dateien ohne Erweiterung
  • ... Dateien mit einem führenden .
  • ... Dateien mit einem Trailing .(wahrscheinlich nicht etwas, auf das Sie jemals unter Windows stoßen werden, aber sie sind möglich )
  • ... Verzeichnisse mit einer "Erweiterung" oder die anderweitig a enthalten .
  • ... Pfade, die mit a enden \
  • ... relative Pfade

Nicht alle Dateipfade folgen der üblichen Formel von X:\Directory\File.ext!

SPECK
quelle
0
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

Your path configuration in App.config file if you are going to get file name dynamically  -

    <userSettings>
        <ConsoleApplication13.Properties.Settings>
          <setting name="Filelocation" serializeAs="String">
            <value>D:\\DeleteFileTest</value>
          </setting>
              </ConsoleApplication13.Properties.Settings>
      </userSettings>
Ritesh Yadav
quelle
Die Frage ist, wie der Dateiname ohne Erweiterung aus einem Dateipfad extrahiert werden kann. Hiermit werden stattdessen die unmittelbaren untergeordneten Dateien eines Verzeichnisses abgerufen, die möglicherweise von einer Konfigurationsdatei angegeben werden oder nicht. Das ist nicht wirklich nah an der gleichen Sache.
Speck