Đưa ra một đường dẫn hệ thống tập tin, có cách nào ngắn hơn để trích xuất tên tệp mà không cần phần mở rộng của nó không?


261

Tôi lập trình trong WPF C #. Tôi có ví dụ như đường dẫn sau:

C:\Program Files\hello.txt

và tôi muốn trích xuất hellotừ nó.

Đường dẫn được stringlấy từ cơ sở dữ liệu. Hiện tại tôi đang sử dụng đoạn mã sau để phân chia đường dẫn '\'và sau đó phân tách lại bằng cách '.':

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

Nó hoạt động, nhưng tôi tin rằng nên có giải pháp ngắn hơn và thông minh hơn cho điều đó. Bất kỳ ý tưởng?


Trong hệ thống của tôi, Path.GetFileName("C:\\dev\\some\\path\\to\\file.cs")đang trả lại cùng một chuỗi và không chuyển đổi nó thành "file.cs" vì một số lý do. Nếu tôi sao chép / dán mã của mình vào trình biên dịch trực tuyến (như rextester.com ), nó có hoạt động không ...?
jbyrd

Câu trả lời:




29

thử

System.IO.Path.GetFileNameWithoutExtension(path); 

bản giới thiệu

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/l Library / system.io.path.getfilenamewithoutextension% 28v = vs.80% 29.aspx


Có vẻ như Path.GetFileNameWithoutExtension () không hoạt động với phần mở rộng tệp> 3 ký tự.
Nolmë Informatique



11

Thử cái này:

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

Điều này sẽ trả về "xin chào" cho fileName.


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

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

1
+1 vì điều này có thể hữu ích trong trường hợp trong đó hoạt động như một Sao lưu trong đó tên tệp chứa các ký tự không hợp lệ [<,> vv trong Path.GetInvalidChars ()].
bhuvin

Điều này thực sự khá hữu ích khi làm việc với đường dẫn trên các máy chủ UNIX ftp.
s952163

6

Thử cái này,

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

2
Bạn đã sử dụng các phương pháp chính xác như được đề cập trong câu trả lời được bình chọn cao nhất.
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

Tôi ngạc nhiên rằng FileVersionInfocó thể được sử dụng trên các tệp không có thông tin phiên bản. Lưu ý rằng GetVersionInfo()chỉ có thể được sử dụng trên các đường dẫn tham chiếu tệp đã tồn tại. Mặc dù một trong hai lớp có thể được sử dụng để lấy tên tệp, câu hỏi cũng được yêu cầu loại bỏ phần mở rộng.
BACON

1

Thứ nhất, mã trong câu hỏi không tạo ra đầu ra được mô tả. Nó trích xuất phần mở rộng tệp ( "txt") chứ không phải tên cơ sở tệp ( "hello"). Để làm điều đó, dòng cuối cùng nên gọi First(), không Last(), như thế này ...

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

    return fileBaseName;
}

Đã thực hiện thay đổi đó, một điều cần suy nghĩ về việc cải thiện mã này là lượng rác mà nó tạo ra:

  • Một string[]chứa một stringcho mỗi đoạn đường dẫn trongpath
  • Một string[]chứa ít nhất một stringcho mỗi .trong đoạn đường dẫn cuối cùng trongpath

Do đó, giải nén tên tập tin cơ sở từ đường dẫn mẫu "C:\Program Files\hello.txt"nên sản xuất (tạm thời) objects "C:", "Program Files", "hello.txt", "hello", "txt", một string[3], và một string[2]. Điều này có thể có ý nghĩa nếu phương thức được gọi trên một số lượng lớn đường dẫn. Để cải thiện điều này, chúng ta có thể tìm kiếm pathchính mình để xác định vị trí bắt đầu và điểm kết thúc của tên cơ sở và sử dụng những để tạo ra một mới 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;
}

Điều này đang sử dụng chỉ mục của ký tự sau cùng \là tên bắt đầu của tên cơ sở và từ đó tìm kiếm đầu tiên .để sử dụng làm chỉ mục của ký tự sau khi kết thúc tên cơ sở. Đây có phải là ngắn hơn so với mã ban đầu? Không hẳn. Đó có phải là một giải pháp "thông minh hơn"? Tôi nghĩ vậy. Ít nhất, nó sẽ là nếu không phải vì ...

Như bạn có thể thấy từ các bình luận, phương pháp trước đó là có vấn đề. Mặc dù nó hoạt động nếu bạn giả sử tất cả các đường dẫn kết thúc bằng một tên tệp có phần mở rộng, nó sẽ đưa ra một ngoại lệ nếu đường dẫn kết thúc bằng \(tức là đường dẫn thư mục) hoặc nếu không chứa phần mở rộng trong phân đoạn cuối. Để khắc phục điều này, chúng ta cần thêm một kiểm tra thêm vào tài khoản khi endIndex-1(tức .là không tìm thấy) ...

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

Bây giờ phiên bản này gần như ngắn hơn bản gốc, nhưng nó hiệu quả hơn và (bây giờ) cũng đúng.

Theo như các phương thức .NET thực hiện chức năng này, nhiều câu trả lời khác đề nghị sử dụng Path.GetFileNameWithoutExtension(), đây là một giải pháp rõ ràng, dễ dàng nhưng không tạo ra kết quả giống như mã trong câu hỏi. Có một sự khác biệt tinh tế nhưng quan trọng giữa GetFileBaseNameUsingSplit()Path.GetFileNameWithoutExtension()( GetFileBaseNameUsingPath()bên dưới): cái trước trích xuất mọi thứ trước cái đầu tiên . và cái sau trích ra mọi thứ trước cái cuối cùng . . Điều này không tạo ra sự khác biệt cho mẫu pathtrong câu hỏi, nhưng hãy xem bảng này so sánh kết quả của bốn phương pháp trên khi được gọi với các đường dẫn khác nhau ...

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

... và bạn sẽ thấy rằng Path.GetFileNameWithoutExtension()mang lại kết quả khác nhau khi đi qua một đường dẫn trong đó tên tệp có phần mở rộng gấp đôi hoặc dẫn đầu và / hoặc theo dõi .. Bạn có thể tự thử nó với mã sau đây ...

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 Mã trong câu hỏi không hoạt động như nhiều người mong đợi trong một số trường hợp góc. Nếu bạn định viết mã thao tác đường dẫn của riêng mình, hãy chắc chắn xem xét ...

  • ... Làm thế nào bạn xác định một "phần mở rộng" (nó là tất cả mọi thứ trước cái đầu tiên .hay mọi thứ trước cái cuối cùng .?)
  • ... tập tin có nhiều phần mở rộng
  • ... tập tin không có phần mở rộng
  • ... tập tin hàng đầu .
  • ... Các tệp có dấu .(có thể không phải là thứ bạn sẽ gặp trên Windows, nhưng chúng có thể )
  • ... thư mục có "phần mở rộng" hoặc nếu không có .
  • ... những con đường kết thúc bằng một \
  • ... đường dẫn tương đối

Không phải tất cả các đường dẫn tập tin theo công thức thông thường của 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>

Câu hỏi là hỏi làm thế nào để trích xuất tên tệp mà không cần mở rộng từ đường dẫn tệp. Thay vào đó, điều này đang truy xuất các tệp con ngay lập tức của một thư mục có thể được chỉ định hoặc không được chỉ định bởi một tệp cấu hình. Những người không thực sự gần với điều tương tự.
BACON
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.