Diberikan jalur sistem file, apakah ada cara yang lebih pendek untuk mengekstrak nama file tanpa ekstensi?


261

Saya memprogram dalam WPF C #. Saya punya misalnya jalur berikut:

C:\Program Files\hello.txt

dan saya ingin mengekstraknya hello.

Path tersebut stringdiambil dari database. Saat ini saya menggunakan kode berikut untuk membagi jalur '\'dan kemudian membagi lagi dengan '.':

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

Ini bekerja, tetapi saya percaya harus ada solusi yang lebih pendek dan lebih cerdas untuk itu. Ada ide?


Dalam sistem saya, Path.GetFileName("C:\\dev\\some\\path\\to\\file.cs")mengembalikan string yang sama dan tidak mengubahnya menjadi "file.cs" karena suatu alasan. Jika saya menyalin / menempelkan kode saya ke kompiler online (seperti rextester.com ), apakah itu berfungsi ...?
jbyrd

Jawaban:




29

mencoba

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


Tampaknya Path.GetFileNameWithoutExtension () tidak berfungsi dengan ekstensi file> 3 karakter.
Nolmë Informatique



11

Coba ini:

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

Ini akan mengembalikan "halo" untuk nama file.


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

string FileName = Location.Substring(Location.LastIndexOf('\\') +
    1);

1
Memberi +1 karena ini mungkin Bermanfaat dalam hal ini berfungsi sebagai Cadangan di mana nama file berisi karakter yang tidak valid [<,> dll di Path.GetInvalidChars ()].
bhuvin

Ini sebenarnya cukup berguna ketika bekerja dengan path pada server ftp UNIX.
s952163

6

Coba ini,

string FilePath=@"C:\mydir\myfile.ext";
string Result=Path.GetFileName(FilePath);//With Extension
string Result=Path.GetFileNameWithoutExtension(FilePath);//Without Extension

2
Anda menggunakan metode yang sama persis seperti yang disebutkan dalam jawaban pilihan tertinggi.
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

Saya terkejut bahwa FileVersionInfodapat digunakan pada file yang tidak memiliki informasi versi. Perhatikan bahwa GetVersionInfo()hanya dapat digunakan pada jalur yang mereferensikan file yang sudah ada. Sementara kedua kelas dapat digunakan untuk mendapatkan nama file, pertanyaannya juga diminta untuk menghapus ekstensi.
BACON

1

Pertama, kode dalam pertanyaan tidak menghasilkan output yang dijelaskan. Itu mengekstrak ekstensi file ( "txt") dan bukan nama file dasar ( "hello"). Untuk melakukan itu baris terakhir harus memanggil First(), bukan Last(), seperti ini ...

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

    return fileBaseName;
}

Setelah melakukan perubahan itu, satu hal yang perlu dipikirkan sejauh memperbaiki kode ini adalah jumlah sampah yang dihasilkannya:

  • Yang string[]mengandungstring untuk setiap segmen jalur dipath
  • A string[]mengandung setidaknya satu stringuntuk masing-masing .di segmen jalur terakhir dipath

Oleh karena itu, mengekstraksi nama file dasar dari jalur sampel "C:\Program Files\hello.txt"harus menghasilkan (sementara)object s "C:", "Program Files", "hello.txt", "hello", "txt", seorang string[3], dan string[2]. Ini bisa menjadi signifikan jika metode ini dipanggil pada sejumlah besar jalur. Untuk memperbaiki ini, kita dapat mencari pathdiri kita sendiri untuk menemukan titik awal dan akhir dari nama dasar dan menggunakan mereka untuk membuat satu baru 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;
}

Ini menggunakan indeks karakter setelah yang terakhir \sebagai awal nama dasar, dan dari sana mencari yang pertama .untuk digunakan sebagai indeks karakter setelah akhir nama dasar. Apakah ini lebih pendek dari kode aslinya? Tidak terlalu. Apakah ini solusi "lebih pintar"? Aku pikir begitu. Setidaknya, itu akan terjadi jika bukan karena fakta bahwa ...

Seperti yang Anda lihat dari komentar, metode sebelumnya bermasalah. Meskipun berfungsi jika Anda menganggap semua jalur diakhiri dengan nama file dengan ekstensi, itu akan menimbulkan pengecualian jika jalur berakhir dengan \(yaitu jalur direktori) atau tidak mengandung ekstensi di segmen terakhir. Untuk memperbaiki ini, kita perlu menambahkan pemeriksaan tambahan untuk akun ketika endIndexadalah -1(yaitu .tidak ditemukan) ...

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;
}

Sekarang versi ini jauh lebih pendek daripada yang asli, tetapi lebih efisien dan (sekarang) benar juga.

Sejauh metode .NET yang menerapkan fungsi ini, banyak jawaban lain menyarankan menggunakan Path.GetFileNameWithoutExtension(), yang merupakan solusi yang jelas dan mudah tetapi tidak menghasilkan hasil yang sama dengan kode dalam pertanyaan. Ada perbedaan yang halus tetapi penting antara GetFileBaseNameUsingSplit()dan Path.GetFileNameWithoutExtension()(di GetFileBaseNameUsingPath()bawah): yang pertama mengekstrak semua sebelum pertama . dan yang kedua mengekstraksi segalanya sebelum yang terakhir . . Ini tidak membuat perbedaan untuk sampel pathdalam pertanyaan, tetapi lihat tabel ini membandingkan hasil dari empat metode di atas ketika dipanggil dengan berbagai jalur ...

| 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()   | ".."                             | ""                                                               |
|-----------------------|---------------------------------------|----------------------------------|------------------------------------------------------------------|

... dan Anda akan melihat bahwa Path.GetFileNameWithoutExtension()menghasilkan hasil yang berbeda ketika melewati jalur di mana nama file memiliki ekstensi ganda atau memimpin dan / atau mengikuti .. Anda dapat mencobanya sendiri dengan kode berikut ...

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 Kode dalam pertanyaan tidak berperilaku seperti yang banyak diharapkan dalam beberapa kasus sudut. Jika Anda akan menulis kode manipulasi jalur Anda sendiri, pastikan untuk mempertimbangkan ...

  • ... bagaimana Anda mendefinisikan "ekstensi" (apakah itu segalanya sebelum yang pertama .atau semuanya sebelum yang terakhir. ?)
  • ... file dengan banyak ekstensi
  • ... file tanpa ekstensi
  • ... file dengan yang utama .
  • ... file dengan trailing .(mungkin bukan sesuatu yang pernah Anda temui di Windows, tetapi itu adalah mungkin )
  • ... direktori dengan "ekstensi" atau yang mengandung a .
  • ... jalur yang diakhiri dengan a \
  • ... jalur relatif

Tidak semua jalur file mengikuti rumus biasa X:\Directory\File.ext!


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>

Pertanyaannya adalah bertanya bagaimana cara mengekstrak nama file tanpa ekstensi dari path file. Ini, sebaliknya, mengambil file anak langsung dari direktori yang mungkin atau mungkin tidak ditentukan oleh file konfigurasi. Itu tidak terlalu dekat dengan hal yang sama.
BACON
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.