【问题标题】:Java: splitting the filename into a base and extensionJava:将文件名拆分为基础和扩展名
【发布时间】: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);

【问题讨论】:

标签: java file


【解决方案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("\\.(?=[^\\.]+$)")
      • 你不能假设只有一个点。亚当:谢谢,我试试看。
      • 这个答案不正确。因为点没有被转义,所以它会返回一个空数组。
      猜你喜欢
      • 2012-12-19
      • 2011-05-17
      • 2012-02-28
      • 2015-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      相关资源
      最近更新 更多