1. 개요

 
Java에서 파일 작업을 할 때 파일 이름을 처리해야 하는 경우가 많습니다. 예를 들어, 때때로 우리는 주어진 파일 이름에서 확장자 없이 이름을 얻고 싶을 때가 있습니다. 즉, 파일 이름의 확장자를 제거하려고 합니다.이 예제에서는 파일 이름에서 확장자를 제거하는 일반적인 방법에 대해 설명합니다.

2. 파일 이름에서 확장자를 제거하는 시나리오

 
처음에 파일 이름에서 확장자를 제거하는 것은 매우 쉬운 문제라고 생각할 수 있습니다.그러나 문제를 자세히 살펴보면 생각보다 복잡할 수 있습니다.우선, 파일 이름이 될 수 있는 유형을 살펴보겠습니다.
  • 확장자 없이 " baeldung"
  • 단일 확장자를 사용하는 경우 가장 일반적인 경우입니다(예: " baeldung.txt ").
  • " baeldung.tar.gz " 와 같은 여러 확장자 ​​사용
  • " .baeldung " 과 같이 확장자가 없는 Dotfile
  • 단일 확장자를 가진 Dotfile(예: " .baeldung.conf "
  • 확장자가 여러 개인 Dotfile(예: " .baeldung.conf.bak ")
다음으로 확장 프로그램을 제거한 후 위의 예에서 예상되는 결과를 나열합니다.
  • " baeldung ": 파일 이름에 확장자가 없습니다. 따라서 파일 이름을 변경해서는 안 되며 " baeldung "을 얻어야 합니다 .
  • " baeldung.txt ": 이것은 간단한 경우입니다. 정확한 결과는 " baeldung " 입니다.
  • " baeldung.tar.gz ": 이 파일 이름은 두 개의 확장자를 포함합니다. 확장자를 하나만 제거하려면 " baeldung.tar "가 결과여야 합니다. 그러나 파일 이름에서 모든 확장자를 제거하려면 " baeldung "이 올바른 결과입니다.
  • " .baeldung ": 이 파일 이름도 확장자가 없으므로 파일 이름도 변경해서는 안 됩니다. 따라서 결과에 " .baeldung " 이 표시될 것으로 예상됩니다.
  • " .baeldung.conf ": 결과는 " .baeldung " 이어야 합니다.
  • " .baeldung.conf.bak ": 확장자를 하나만 제거하려면 결과가 ".baeldung.conf"여야 합니다. 그렇지 않으면 " .baeldung "이 모든 확장자를 제거하는 경우 예상되는 출력입니다.
이 사용방법(예제)에서는 Guava 및 Apache Commons IO에서 제공하는 유틸리티 메서드가 위에 나열된 모든 경우를 처리할 수 있는지 테스트합니다.또한 주어진 파일 이름에서 확장자(또는 확장자)를 제거하는 문제를 해결하는 일반적인 방법에 대해서도 논의합니다.

3. 구아바 라이브러리 테스트

 
버전 14.0부터

Guava

Files.getNameWithoutExtension()

메서드를 도입했습니다 . 이를 통해 주어진 파일 이름에서 확장자를 쉽게 제거할 수 있습니다.유틸리티 메서드를 사용하려면 클래스 경로에 Guava 라이브러리를 추가해야 합니다. 예를 들어 Maven을 빌드 도구로 사용하는 경우 pom.xml  파일에

Guava 의존성

추가할 수 있습니다 .
<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>30.0-jre</version>
</dependency>
먼저 이 메서드의 구현을 살펴보겠습니다.
public static String getNameWithoutExtension(String file) {
   ...
   int dotIndex = fileName.lastIndexOf('.');
   return (dotIndex == -1) ? fileName : fileName.substring(0, dotIndex);
 }
구현은 매우 간단합니다. 파일 이름에 점이 포함된 경우 메서드는 마지막 점에서 파일 이름 끝까지 잘라냅니다. 그렇지 않고 파일 이름에 점이 포함되어 있지 않으면 변경 없이 원래 파일 이름이 반환됩니다.따라서

Guava의 getNameWithoutExtension()  메서드는 확장자가 없는 도트 파일에 대해 작동하지 않습니다. 

다음을 증명하는 테스트를 작성해 보겠습니다.
@Test
public void givenDotFileWithoutExt_whenCallGuavaMethod_thenCannotGetDesiredResult() {
    //negative assertion
    assertNotEquals(".baeldung", Files.getNameWithoutExtension(".baeldung"));
}
확장자가 여러 개인 파일 이름을 처리할 때

이 방법은 파일 이름에서 모든 확장자를 제거하는 옵션을 제공하지 않습니다.

@Test
public void givenFileWithoutMultipleExt_whenCallGuavaMethod_thenCannotRemoveAllExtensions() {
    //negative assertion
    assertNotEquals("baeldung", Files.getNameWithoutExtension("baeldung.tar.gz"));
}

4. Apache Commons IO 라이브러리 테스트

 
Guava 라이브러리와 마찬가지로 인기 있는

Apache Commons IO

라이브러리는 FilenameUtils 클래스

removeExtension()

메서드를 제공하여

파일

이름 확장자를 빠르게 제거합니다.
이 방법을 살펴보기 전에

Apache Commons IO 의존성

pom.xml에

추가해 보겠습니다 .
<dependency>
    <groupId>commons-io</groupId>
    <artifactId>commons-io</artifactId>
    <version>2.8.0</version>
</dependency>
구현은 Guava의

getNameWithoutExtension()

메서드 와 유사합니다 .
public static String removeExtension(final String filename) {
    ...
    final int index = indexOfExtension(filename); //used the String.lastIndexOf() method
    if (index == NOT_FOUND) {
  	return filename;
    } else {
	return filename.substring(0, index);
    }
}
따라서

Apache Commons IO의 방법은 dotfile에서도 작동하지 않습니다

.
@Test
public void givenDotFileWithoutExt_whenCallApacheCommonsMethod_thenCannotGetDesiredResult() {
    //negative assertion
    assertNotEquals(".baeldung", FilenameUtils.removeExtension(".baeldung"));
}

파일 이름에 확장자가 여러 개인 경우 removeExtension() 메서드는 모든 확장자를 제거할 수 없습니다.

@Test
public void givenFileWithoutMultipleExt_whenCallApacheCommonsMethod_thenCannotRemoveAllExtensions() {
    //negative assertion
    assertNotEquals("baeldung", FilenameUtils.removeExtension("baeldung.tar.gz"));
}

5. 파일 이름에서 확장자 제거

 
지금까지 널리 사용되는 두 라이브러리의 파일 이름에서 확장자를 제거하는 유틸리티 메서드를 살펴보았습니다. 두 방법 모두 매우 편리하며 가장 일반적인 경우에 적합합니다.그러나 다른 한편으로는 다음과 같은 몇 가지 단점이 있습니다.
  • dotfile 에서는 작동하지 않습니다(예: " .baeldung "
  • 파일 이름에 여러 확장자가 있는 경우 마지막 확장자만 제거하거나 모든 확장자를 제거하는 옵션을 제공하지 않습니다.
다음으로 모든 경우를 포괄하는 메서드를 작성해 보겠습니다.
public static String removeFileExtension(String filename, boolean removeAllExtensions) {
    if (filename == null || filename.isEmpty()) {
        return filename;
    }

    String extPattern = "(?<!^)[.]" + (removeAllExtensions ? ".*" : "[^.]*$");
    return filename.replaceAll(extPattern, "");
}
모든 확장자를 제거하거나 파일 이름에서 마지막 확장자만 제거하는 옵션을 제공하기 위해

부울

매개변수 

removeAllExtensions

추가했습니다 .
이 방법의 핵심 부분은

정규식

패턴입니다.

정규식

패턴 이 무엇을 하는지 이해해 봅시다 .
  • “(?<!^)[.]”정규식 에서 부정 lookbehind 를  사용합니다 . 점"과 일치합니다 . "는 파일 이름의 시작 부분에 있지 않습니다.
  • " (?<!^)[.].* " - removeAllExtensions 옵션이 설정되어 있으면 파일 이름이 끝날 때까지 첫 번째로 일치하는 점과 일치합니다.
  • (?<!^)[.][^.]*$ ” – 이 패턴은 마지막 확장자에만 일치합니다.
마지막으로, 우리의 방법이 모든 다른 경우에 작동하는지 확인하기 위해 몇 가지 테스트 방법을 작성해 보겠습니다.
@Test
public void givenFilenameNoExt_whenCallFilenameUtilMethod_thenGetExpectedFilename() {
    assertEquals("baeldung", MyFilenameUtil.removeFileExtension("baeldung", true));
    assertEquals("baeldung", MyFilenameUtil.removeFileExtension("baeldung", false));
}

@Test
public void givenSingleExt_whenCallFilenameUtilMethod_thenGetExpectedFilename() {
    assertEquals("baeldung", MyFilenameUtil.removeFileExtension("baeldung.txt", true));
    assertEquals("baeldung", MyFilenameUtil.removeFileExtension("baeldung.txt", false));
}

@Test
public void givenDotFile_whenCallFilenameUtilMethod_thenGetExpectedFilename() {
    assertEquals(".baeldung", MyFilenameUtil.removeFileExtension(".baeldung", true));
    assertEquals(".baeldung", MyFilenameUtil.removeFileExtension(".baeldung", false));
}

@Test
public void givenDotFileWithExt_whenCallFilenameUtilMethod_thenGetExpectedFilename() {
    assertEquals(".baeldung", MyFilenameUtil.removeFileExtension(".baeldung.conf", true));
    assertEquals(".baeldung", MyFilenameUtil.removeFileExtension(".baeldung.conf", false));
}

@Test
public void givenDoubleExt_whenCallFilenameUtilMethod_thenGetExpectedFilename() {
    assertEquals("baeldung", MyFilenameUtil.removeFileExtension("baeldung.tar.gz", true));
    assertEquals("baeldung.tar", MyFilenameUtil.removeFileExtension("baeldung.tar.gz", false));
}

@Test
public void givenDotFileWithDoubleExt_whenCallFilenameUtilMethod_thenGetExpectedFilename() {
    assertEquals(".baeldung", MyFilenameUtil.removeFileExtension(".baeldung.conf.bak", true));
    assertEquals(".baeldung.conf", MyFilenameUtil.removeFileExtension(".baeldung.conf.bak", false));
}

6. 결론

 
이 기사에서는 주어진 파일 이름에서 확장자를 제거하는 방법에 대해 이야기했습니다.먼저 확장을 제거하는 다양한 시나리오에 대해 논의했습니다.다음으로 널리 사용되는 두 라이브러리인 Guava 및 Apache Commons IO에서 제공하는 방법을 소개했습니다. 그것들은 꽤 편리하고 일반적인 경우에 작동하지만 도트 파일에는 작동하지 않습니다. 또한 단일 확장 또는 모든 확장을 제거하는 옵션을 제공하지 않습니다.마지막으로 모든 요구 사항을 충족하는 방법을 구축했습니다.항상 그렇듯이 기사의 전체 소스 코드는

GitHub에서

사용할 수 있습니다 .
Junit footer banner