자바 : 파일 이름을 기본 및 확장으로 분할


83

파일 기본 이름과 확장자를 얻는 더 좋은 방법이 있습니까?

File f = ...
String name = f.getName();
int dot = name.lastIndexOf('.');
String base = (dot == -1) ? name : name.substring(0, dot);
String extension = (dot == -1) ? "" : name.substring(dot+1);

7
commons-io를 살펴보십시오 FilenameUtils. 그것은이 getBaseName(..)getExtension(..)방법을.
Bozho 2010

의 경우 에만 확장을 참조 stackoverflow.com/questions/3571223/...을 .
Andy Thomas

답변:


168

다른 사람들이 언급 한 것을 알고 String.split있지만 여기에는 두 개의 토큰 (기본 및 확장) 만 생성하는 변형이 있습니다 .

String[] tokens = fileName.split("\\.(?=[^\\.]+$)");

예를 들면 :

"test.cool.awesome.txt".split("\\.(?=[^\\.]+$)");

수율 :

["test.cool.awesome", "txt"]

정규식은 Java가 임의의 수의 비 기간이 뒤 따르고 입력이 끝나는 기간을 분할하도록 지시합니다. 이 정의와 일치하는 기간이 하나뿐입니다 (즉, 마지막 기간).

기술적으로 정규적으로 말하면이 기술을 폭이 0 인 긍정 예측 이라고 합니다 .


BTW, 경로를 분할하고 슬래시가있는 경로를 사용하여 점 확장자를 포함하지만 이에 국한되지 않는 전체 파일 이름을 얻으려면,

    String[] tokens = dir.split(".+?/(?=[^/]+$)");

예를 들면 :

    String dir = "/foo/bar/bam/boozled"; 
    String[] tokens = dir.split(".+?/(?=[^/]+$)");
    // [ "/foo/bar/bam/" "boozled" ] 

2
나는 사람들이 ;-) 의존성을 두려워 왜 아무 생각이 없다
Bozho

3
@Bozho : 나는 도서관이 이러한 유형의 문제에 대해 더 나은 해결책이라는 데 동의합니다. 그것은 다른 사람들이 당신을 위해 유지하고 생각할 수있게합니다 (그게 제가 당신의 대답을 찬성 한 이유입니다!). 이것은 사소하게 들릴지 모르지만 Apache 라이브러리를 포함하는 것을 고려할 때 항상 주저하는 부분이 있습니다. 과거에 일부 물건으로 "JAR 지옥"을 겪었 기 때문입니다.
Adam Paynter

4
@Bozho : Adam의 100 % 맞습니다. 이 문제는 내가 또 다른 라이브러리를 가져가는 것을 보증하기에 충분하지 않습니다.하지만 이미 다른 이유로 commons-io를 사용하고 있다면 Filenameutils를 사용합니다.
Jason S

1
@Jason : 정규 표현식 : 계속해서주는 선물. :)
Adam Paynter 2011 년

3
@Bozho-풍자? 진짜 질문은 왜 자바가 당신이 실제로하고 싶은 일을 쉽게 할 수 있도록 만드는 중복 클래스의 끝없는 더미와 함께 오는 이유입니다. Python에는 이미 원하는 모든 유용한 기능이 내장되어 있기 때문에 Python의 Apache-Commons와 동등한 것은 없습니다. C #은 바퀴를 재발 명하거나 다른 사람이 발명 한 바퀴를 얻는 방법을 알아 내지 않고 고유 한 문제에 집중할 수있는 언어의 또 다른 예인 것 같습니다.
ArtOfWarfare

84

오래된 질문이지만 일반적으로이 솔루션을 사용합니다.

import org.apache.commons.io.FilenameUtils;

String fileName = "/abc/defg/file.txt";

String basename = FilenameUtils.getBaseName(fileName);
String extension = FilenameUtils.getExtension(fileName);
System.out.println(basename); // file
System.out.println(extension); // txt (NOT ".txt" !)

Windows에서 작업하고 문자열 "fileName"이 "D : \ resources \ ftp_upload.csv"이면 작동하지 않습니다. 도와 주시겠습니까?
NIKHIL CHAURASIA

3
@NIKHILCHAURASIA 백 슬래시를 두 배로 이스케이프해야합니다. 예 : "D : \\ resources \\ ftp_upload.csv".
Ricket 2016 년

8

출처 : http://www.java2s.com/Code/Java/File-Input-Output/Getextensionpathandfilename.htm

그러한 유틸리티 클래스 :

class Filename {
  private String fullPath;
  private char pathSeparator, extensionSeparator;

  public Filename(String str, char sep, char ext) {
    fullPath = str;
    pathSeparator = sep;
    extensionSeparator = ext;
  }

  public String extension() {
    int dot = fullPath.lastIndexOf(extensionSeparator);
    return fullPath.substring(dot + 1);
  }

  public String filename() { // gets filename without extension
    int dot = fullPath.lastIndexOf(extensionSeparator);
    int sep = fullPath.lastIndexOf(pathSeparator);
    return fullPath.substring(sep + 1, dot);
  }

  public String path() {
    int sep = fullPath.lastIndexOf(pathSeparator);
    return fullPath.substring(0, sep);
  }
}

용법:

public class FilenameDemo {
  public static void main(String[] args) {
    final String FPATH = "/home/mem/index.html";
    Filename myHomePage = new Filename(FPATH, '/', '.');
    System.out.println("Extension = " + myHomePage.extension());
    System.out.println("Filename = " + myHomePage.filename());
    System.out.println("Path = " + myHomePage.path());
  }
}

4
basename()더 좋은 이름이 아닌 것filename()
nimcap

확장자가없는 경우 (예 : "/ etc / hosts"와 같은 파일 이름) 이것은 ""가 아닌 확장자로 "hosts"를 반환합니다. 라이브러리 급 유틸리티 클래스는 코너 케이스를 처리해야합니다.
Zach-M

6

http://docs.oracle.com/javase/6/docs/api/java/io/File.html#getName ()

에서 http://www.xinotes.org/notes/note/774/ :

Java에는 주어진 파일 경로에 대한 기본 이름과 디렉토리 이름을 가져 오는 내장 함수가 있지만 함수 이름이 그렇게 명확하지는 않습니다.

import java.io.File;

public class JavaFileDirNameBaseName {
    public static void main(String[] args) {
    File theFile = new File("../foo/bar/baz.txt");
    System.out.println("Dirname: " + theFile.getParent());
    System.out.println("Basename: " + theFile.getName());
    }
}

4
java.io.File.getName ()은 확장자가있는 이름을 리턴합니다.
Bram 2011

2
나는 "확장자":-) 같은 더 그런 일이 없다고 생각하는 것을 선호

3
하지만 질문은 확장을 얻는 것에 관한 것입니다 ...
user85421

4

파일 확장자는 깨진 개념입니다

그리고 그것에 대한 신뢰할 수있는 기능 없습니다. 예를 들어 다음 파일 이름을 고려하십시오.

archive.tar.gz

확장 무엇입니까 ? DOS 사용자는 이름을 선호했을 것 archive.tgz입니다. 때로는 파일을 먼저 압축 해제 (파일 생성)하는 어리석은 Windows 응용 프로그램을 본 .tar다음 아카이브 내용을 보려면 다시 열어야합니다.

이 경우 파일 확장자에 대한보다 합리적인 개념은 .tar.gz. 이 또한 .tar.bz2, .tar.xz, .tar.lz.tar.lzma파일 "확장자"를 사용한다. 그러나 마지막 점에서 분할할지 아니면 마지막 점에서 두 번째 점에서 분할할지 어떻게 결정할까요?

대신 MIME 유형을 사용하십시오.

Java 7 함수 Files.probeContentType 은 파일 확장자를 신뢰하는 것보다 파일 유형을 감지하는 데 훨씬 더 신뢰할 수 있습니다. 웹 브라우저와 스마트 폰뿐만 아니라 거의 모든 유닉스 / 리눅스 세계는 이미 이런 식으로하고 있습니다.


6
이것은 질문에 어떻게 대답합니까? 나도 연장선을 떼어 File놓지 Path말자.
Andreas Abel

@ andreas.abel을 다시 한번 말씀 드리겠습니다. 파일 확장자는 깨어진 개념입니다. 그들은 믿을 수 없으며, DOS 8 + 3 파일 이름을 제외하고 잘 정의되지 않습니다 (고려 .tar.gz.tgz유닉스에 너무 공통). 대신 MIME 유형을 사용하십시오.
Has QUIT--Anony-Mousse

1
Anony - 무스 음 @, 나는 원칙적으로 동의하지만 모든 시스템의 9만9천9백99퍼센트 I 상호 작용 파일 이름이 아닌 MIME 타입 사용에
기독교 사우어

Files.probeContentType올바른 확장자를 갖기 위해 파일 이름에 의존하는 대신 사용하는 데 문제가 있습니까?
Has QUIT--Anony-Mousse

3
이것은 질문에 대한 답이 아닙니다. 파일 이름, 영화가 이름 + 확장자 인 사용 사례가 있습니다. MIME 유형을 사용하여 이름을 어떻게 추출합니까?
Niek

1

코드에 어떤 문제가 있습니까? 깔끔한 유틸리티 방식으로 싸여도 괜찮습니다.

더 중요한 것은 구분자로 사용할 첫 번째 또는 마지막 점입니다. 첫 번째는 "setup-2.5.1.exe"와 같은 파일 이름에 적합하지 않으며 마지막은 "mybundle.tar.gz"와 같은 여러 확장자를 가진 파일 이름에 적합하지 않습니다.



-3

아마도 String # split을 사용할 수 있습니다 .

귀하의 의견에 답변하려면 :

둘 이상이있을 수 있는지 잘 모르겠습니다. 파일 이름에 있지만 더 많은 점이 있더라도 분할을 사용할 수 있습니다. 예를 들어 다음을 고려하십시오.

String input = "boo.and.foo";

String[] result = input.split(".");

다음을 포함하는 배열이 반환됩니다.

{ "boo", "and", "foo" }

따라서 배열의 마지막 인덱스가 확장이고 다른 모든 인덱스가 기본임을 알 수 있습니다.


음, 예,하지만 .문자열 에서 마지막 정규식을 찾아야 합니다
Jason S

1
잘 모르겠지만 "."만 사용하면 안 되나요? 아니면 파일 이름에 점이 두 개 이상 있습니까?

2
나는 이것이 효과가있을 것이라고 생각한다 :fileName.split("\\.(?=[^\\.]+$)")
Adam Paynter

1
점이 하나 뿐이라고 가정 할 수 없습니다. Adam : 감사합니다. 시도해 볼게요.
Jason S

4
이 대답은 틀 렸습니다. 점은 이스케이프되지 않기 때문에 빈 배열을 반환합니다.
aled
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.