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

Posted

技术标签:

【中文标题】Java:将文件名拆分为基础和扩展名【英文标题】:Java: splitting the filename into a base and extension 【发布时间】:2011-05-31 13:31:27 【问题描述】:

有没有比之类的更好的方法来获取文件基名和扩展名

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

【问题讨论】:

看看commons-ioFilenameUtils。它有getBaseName(..)getExtension(..) 方法。 对于扩展,见***.com/questions/3571223/…。 【参考方案1】:

我知道其他人提到了String.split,但这里有一个变体,只产生 两个 标记(基础和扩展):

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

例如:

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

产量:

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

正则表达式告诉 Java 在后面跟着任意数量的非句点的任何句点上进行拆分,然后是输入的结尾。只有一个时期符合这个定义(即last时期)。

技术上 从正则上讲,这种技术称为zero-width positive lookahead。


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

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

例如:

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

【讨论】:

我不知道人们为什么害怕依赖 ;-) @Bozho:我同意图书馆是这类问题的更好解决方案。它可以让其他人为您进行维护和思考(这就是我投票赞成您的答案的原因!)。这听起来可能微不足道,但是当我考虑包含 Apache 库时,我的一部分总是犹豫不决,因为我过去曾用他们的一些东西遭受过“JAR 地狱”(我知道,这很微不足道)。 @Bozho:亚当 100% 正确。这个问题不足以保证我使用另一个库——但如果我已经因为其他原因在使用 commons-io,那么我会使用 Filenameutils。 @Jason:正则表达式:不断给予的礼物。 :) @Bozho - 讽刺?真正的问题是,为什么 java 带有无穷无尽的冗余类,这些类如此接近于让您轻松地做您真正想做的事情,但令人沮丧的是,它们从未真正做到过。 Python 中没有与 Apache-Commons 等价的东西,因为 Python 已经内置了您想要的所有有用的东西。 C# 似乎是另一种语言示例,您可以专注于自己的独特问题,而不必弄清楚如何重新发明***或去获取别人发明的***。【参考方案2】:

老问题,但我通常使用这个解决方案:

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" 则不起作用,您能帮忙吗? @NIKHILCHAURASIA 您需要通过将反斜杠加倍来转义它们。比如:“D:\\resources\\ftp_upload.csv”。【参考方案3】:

来源: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());
  

【讨论】:

basename() 将是一个更好的名称,而不是 filename() 如果没有扩展名(例如“/etc/hosts”之类的文件名),这将返回“hosts”作为扩展名(而不是“”)。库级实用程序类应该处理极端情况。【参考方案4】:

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

【讨论】:

java.io.File.getName() 返回带有扩展名的名称。 我更愿意认为没有像“扩展”这样的东西:-)【参考方案5】:

您的代码有什么问题?包裹在一个简洁的实用方法中就可以了。

更重要的是使用什么作为分隔符——第一个或最后一个点。第一个不适用于“setup-2.5.1.exe”之类的文件名,最后一个不适用于具有多个扩展名的文件名,例如“mybundle.tar.gz”。

【讨论】:

【参考方案6】:

文件扩展名是一个破碎的概念

并且存在没有可靠的功能。例如考虑这个文件名:

archive.tar.gz

什么是扩展? DOS 用户会更喜欢名称archive.tgz。有时您会看到 愚蠢 Windows 应用程序首先解压缩文件(生成 .tar 文件),然后您必须再次打开它才能看到存档内容。

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

改用 mime 类型。

Java 7 函数Files.probeContentType 检测文件类型可能比信任文件扩展名更可靠。几乎所有的 Unix/Linux 世界以及您的网络浏览器和智能手机都已经这样做了。

【讨论】:

这如何回答这个问题? FilePath 都不允许我拆分扩展名。 @andreas.abel 让我重复一遍:文件扩展名是一个错误的概念。除了 DOS 8+3 文件名(考虑 .tar.gz.tgz 在 unix 上都太常见),它们不可靠,也没有明确定义。 改用 mime 类型。 @Anony-Mousse 好吧,我原则上同意,但我与之交互的所有系统中有 99,999% 使用文件名,而不是 mime 类型 使用Files.probeContentType而不是依赖文件名来获得正确的扩展名的问题在哪里? 这不能回答问题。我有一个用例,其中文件名(电影)是名称+扩展名。如何使用 mime-types 提取名称?【参考方案7】:

您还可以使用 java 正则表达式。 String.split() 也在内部使用表达式。参考http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Pattern.html

【讨论】:

【参考方案8】:

也许你可以使用String#split

回答您的评论:

我不确定是否可以有多个 .在文件名中,但无论如何,即使有更多的点,您也可以使用拆分。考虑例如那:

String input = "boo.and.foo";

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

这将返回一个数组,其中包含:

 "boo", "and", "foo" 

所以你会知道数组中的最后一个索引是扩展,所有其他的都是基础。

【讨论】:

嗯,是的,但我必须找出字符串中最后一个 . 的正则表达式 嗯我不确定,但你不能只使用“。”吗?还是文件名中超过 1 个点? 我认为这可行:fileName.split("\\.(?=[^\\.]+$)") 你不能假设只有一个点。亚当:谢谢,我试试看。 这个答案不正确。因为点没有被转义,所以它会返回一个空数组。

以上是关于Java:将文件名拆分为基础和扩展名的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中从文件扩展名中拆分文件名?

有啥方法可以将 GraphQL 查询的多个 Fragment 扩展拆分为多个调用?

JSP简介和基础语法

在java中获取文件扩展名[重复]

Java学习必备-文件扩展名

Java千百问_08JDK详解(004)_jdk基础扩展类库都有什么