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 世界以及您的网络浏览器和智能手机都已经这样做了。
【讨论】:
这如何回答这个问题?File
和 Path
都不允许我拆分扩展名。
@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:将文件名拆分为基础和扩展名的主要内容,如果未能解决你的问题,请参考以下文章