Java:将文件名分为基础和扩展名


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(..)方法。
博佐

对于扩展名,请参阅stackoverflow.com/questions/3571223/…
安迪·托马斯

Answers:


168

我知道其他人提到过String.split,但这是一个仅产生两个标记(基本标记和扩展标记)的变体:

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

例如:

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

产量:

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

正则表达式告诉Java在任何时间段前分割,之后是任意数量的非时间段,然后是输入的结尾。只有一个符合此定义的时间段(即最后一个时间段)。

技术上来讲,则地说,该技术称为零宽度正向超前


顺便说一句,如果您想分割路径并使用带有正斜杠的路径来获取完整文件名(包括但不限于点扩展名),

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

例如:

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

2
我不知道为什么人们会害怕依赖;-)
Bozho 2010年

3
@Bozho:我同意图书馆是解决此类问题的更好解决方案。它可以让其他人为您进行维护和思考(这就是为什么我投票赞成您的答案!)。这听起来似乎微不足道,但是当我考虑包括一个Apache库时,我当中的某些人总是会犹豫,因为过去我在使用它们的某些东西时遭受了“ JAR地狱”(我知道,这是微不足道的)。
亚当·佩恩特

4
@Bozho:亚当100%正确。这个问题不足以保证我可以使用另一个库-但是如果由于其他原因我已经在使用commons-io,那么我将使用Filenameutils。
詹森·S

1
@Jason:正则表达式:不断给予的礼物。:)
Adam Paynter

3
@Bozho-讽刺?真正的问题是,为什么Java带有无穷无尽的冗余类堆,它们如此接近以至于可以很容易地完成您实际想要做的事情,但是令人沮丧的是却从未真正做到。在Python中没有与Apache-Commons等效的东西,因为Python只是已经内置了所有您想要的有用的东西。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)

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 2012年

如果没有扩展名(例如,文件名如“ / 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

2
我更倾向于认为不存在“扩展”之类的东西:-)

3
但问题是关于获取扩展名的问题
user85421 '19

4

文件扩展名是一个坏概念

那里 存在它没有可靠的功能。例如考虑以下文件名:

archive.tar.gz

什么扩展名?DOS用户更喜欢该名称archive.tgz。有时候你看到愚蠢的Windows应用程序首先解压缩文件(.tar文件),然后必须再次将其打开以查看存档内容。

在这种情况下,文件扩展名的概念更为合理.tar.gz。也有.tar.bz2.tar.xz.tar.lz.tar.lzma在使用文件“扩展”。但是,您将如何决定是在最后一个点还是在倒数第二个点拆分?

请改用mime-types。

Java 7函数Files.probeContentType可能比信任文件扩展名更可靠地检测文件类型。几乎所有的Unix / Linux世界以及您的Webbrowser和Smartphone都已经采用这种方式。


6
这如何回答这个问题?既不File也不Path让我分裂出去的延伸。
Andreas Abel

@ andreas.abel让我重复一遍:文件扩展名是一个残破的概念。除了DOS 8 + 3文件名外,它们不可靠,也没有很好的定义(考虑.tar.gz.tgzUNIX上普遍使用的文件名相比)。请改用mime类型。
已退出-Anony-Mousse

1
@ Anony-Mousse好吧,我原则上同意,但是与我互动的所有系统的99,999%使用文件名,而不是mime类型
Christian Sauer

使用Files.probeContentType而不是依靠文件名进行正确扩展的问题出在哪里?
已退出–Anony-Mousse

3
这不能回答问题。我有一个用例,其中文件名(电影)是名称+扩展名。如何使用mime-types提取名称?
尼克,

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 2010年

1
嗯,我不确定,但是您不能只使用“。”吗?还是文件名中超过1个点?

2
我认为这会起作用:fileName.split("\\.(?=[^\\.]+$)")
Adam Paynter 2010年

1
您不能假设只有一个点。亚当:谢谢,我会尝试的。
杰森S

4
这个答案是不正确的。因为该点未转义,所以它将返回一个空数组。
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.