파일 시스템 경로가 주어지면 확장자없이 파일 이름을 추출하는 더 짧은 방법이 있습니까?


260

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();

작동하지만 더 짧고 똑똑한 솔루션이 있어야한다고 생각합니다. 어떤 생각?


내 시스템 Path.GetFileName("C:\\dev\\some\\path\\to\\file.cs")에서 동일한 문자열을 반환하고 어떤 이유로 "file.cs"로 변환하지 않습니다. rextester.com 과 같은 온라인 컴파일러에 코드를 복사하여 붙여 넣으면 작동합니다 ...?
jbyrd

답변:




29

시험

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


Path.GetFileNameWithoutExtension ()이 3자를 초과하는 파일 확장자로 작동하지 않는 것 같습니다.
Nolmë Informatique



11

이 시도:

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

fileName에 "hello"를 반환합니다.


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

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

1
파일 이름에 Path.GetInvalidChars ()에서 유효하지 않은 문자 [<,> 등이 포함 된 백업으로 작동하는 경우에 도움이 될 수 있으므로 +1입니다.
bhuvin

이것은 UNIX ftp 서버에서 경로로 작업 할 때 실제로 매우 유용합니다.
s952163

6

이 시도,

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

2
최고 투표 답변에 언급 된 것과 동일한 방법을 사용했습니다.
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

FileVersionInfo버전 정보가없는 파일에 사용할 수 있다는 것이 놀랍습니다 . 주 GetVersionInfo()에만 이미 존재하는 파일을 참조 경로에서 사용할 수 있습니다. 두 클래스 중 하나를 사용하여 파일 이름을 가져올 수 있지만 질문도 확장명을 제거하도록 요청했습니다.
BACON

1

먼저, 문제의 코드는 설명 된 출력을 생성하지 않습니다. 파일 기본 이름 ( )이 아닌 파일 확장자 ( "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;
}

이러한 코드를 변경 한 후이 코드를 개선 할 때 고려해야 할 사항은 생성되는 가비지 양입니다.

  • 의 각 경로 세그먼트에 대해 string[]하나 string를 포함path
  • string[]적어도 하나 포함하는 string각각 .의 마지막 경로 세그먼트하여path

따라서, 샘플 경로로부터 기본 파일 이름을 추출하여 "C:\Program Files\hello.txt"생성한다 (임시) object"C:", "Program Files", "hello.txt", "hello", "txt"하는 string[3], 및 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 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;
}

이제이 버전은 원본보다 거의 짧지 않지만 더 효율적이고 (현재) 정확합니다.

지금까지이 기능을 구현 .NET 방법으로, 많은 다른 답변은 사용하는 것이 좋습니다 Path.GetFileNameWithoutExtension()명백한 쉬운 솔루션입니다하지만, 이는 동일한 결과를 생성하지 않습니다 질문의 코드로합니다. GetFileBaseNameUsingSplit()Path.GetFileNameWithoutExtension()( GetFileBaseNameUsingPath()아래) 에는 미묘하지만 중요한 차이점이 있습니다. 전자는 첫 번째 . 전에 모든 것을 추출하고 후자는 마지막 전에 모든 것을 추출합니다 .. 이것은 path문제 의 샘플 과 차이가 없지만 다양한 경로로 호출 될 때 위의 네 가지 방법의 결과를 비교하는이 표를 살펴보십시오 ...

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

... 그리고 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 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 문제 의 코드 는 일부 모퉁이의 경우 예상대로 동작하지 않습니다 . 자신 만의 경로 조작 코드를 작성하려면 다음 사항을 고려해야합니다.

  • ... "확장"을 정의하는 방법 (첫 번째 .이전의 모든 것 또는 마지막 이전의 모든 것 .입니까?)
  • ... 여러 확장자를 가진 파일
  • ... 확장자가없는 파일
  • ... 리딩이있는 파일 .
  • ... 후행이있는 파일 .(아마도 Windows에서는 발생하지 않지만 가능할 수 있습니다 )
  • ... "확장"이 있거나 그렇지 않은 디렉토리 .
  • ...로 끝나는 경로 \
  • ... 상대 경로

모든 파일 경로가 일반적인 공식을 따르는 것은 아닙니다 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>

문제는 파일 경로에서 확장자없이 파일 이름을 추출하는 방법을 묻는 것입니다. 대신, 구성 파일에 의해 지정되거나 지정되지 않을 수있는 디렉토리의 직계 하위 파일을 검색합니다. 그것들은 실제로 같은 것에 가깝지 않습니다.
BACON
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.