我如何得到一个文件的文件扩展名在Java?

明确一点,我并不是在寻找MIME类型。

假设我有以下输入:/path/to/file/foo.txt

我想要一种方法来打破这个输入,特别是到.txt扩展。在Java中有任何内置的方法来做到这一点吗?我希望避免编写自己的解析器。

812842 次浏览

你真的需要一个“解析器”吗?

String extension = "";


int i = fileName.lastIndexOf('.');
if (i > 0) {
extension = fileName.substring(i+1);
}

假设您正在处理简单的类似windows的文件名,而不是像archive.tar.gz这样的文件名。

顺便说一下,对于目录可能有一个'。',但文件名本身没有(如/path/to.a/file),你可以这样做

String extension = "";


int i = fileName.lastIndexOf('.');
int p = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));


if (i > p) {
extension = fileName.substring(i+1);
}
// Modified from EboMike's answer


String extension = "/path/to/file/foo.txt".substring("/path/to/file/foo.txt".lastIndexOf('.'));

扩展应该有“.txt”在它运行时。

JFileChooser怎么样?这并不简单,因为你需要解析它的最终输出…

JFileChooser filechooser = new JFileChooser();
File file = new File("your.txt");
System.out.println("the extension type:"+filechooser.getTypeDescription(file));

这是一个MIME类型…

好吧……我忘了你不想知道它的MIME类型。

下面链接中的有趣代码: # EYZ0 < / p >

/*
* Get the extension of a file.
*/
public static String getExtension(File f) {
String ext = null;
String s = f.getName();
int i = s.lastIndexOf('.');


if (i > 0 &&  i < s.length() - 1) {
ext = s.substring(i+1).toLowerCase();
}
return ext;
}
< p >相关问题: # EYZ0 < / p >

如何(使用Java 1.5 RegEx):

    String[] split = fullFileName.split("\\.");
String ext = split[split.length - 1];

如果您使用番石榴库,则可以使用Files实用程序类。它有一个特定的方法getFileExtension()。例如:

String path = "c:/path/to/file/foo.txt";
String ext = Files.getFileExtension(path);
System.out.println(ext); //prints txt

此外,您还可以使用类似的函数获得文件名,getNameWithoutExtension ():

String filename = Files.getNameWithoutExtension(path);
System.out.println(filename); //prints foo

下面是一个正确处理.tar.gz的方法,即使是在目录名中有圆点的路径中:

private static final String getExtension(final String filename) {
if (filename == null) return null;
final String afterLastSlash = filename.substring(filename.lastIndexOf('/') + 1);
final int afterLastBackslash = afterLastSlash.lastIndexOf('\\') + 1;
final int dotIndex = afterLastSlash.indexOf('.', afterLastBackslash);
return (dotIndex == -1) ? "" : afterLastSlash.substring(dotIndex + 1);
}

创建afterLastSlash是为了更快地找到afterLastBackslash,因为如果字符串中有一些斜杠,它就不必搜索整个字符串。

原始的String中的char[]被重用,在那里没有添加垃圾,JVM可能会注意到afterLastSlash立即是垃圾,以便将它放在堆栈而不是堆上

在本例中,从Apache Commons IO使用FilenameUtils.getExtension

下面是一个如何使用它的例子(你可以指定完整路径或只是文件名):

import org.apache.commons.io.FilenameUtils;


// ...


String ext1 = FilenameUtils.getExtension("/path/to/file/foo.txt"); // returns "txt"
String ext2 = FilenameUtils.getExtension("bar.exe"); // returns "exe"

Maven的依赖:

<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>

Gradle Groovy DSL

implementation 'commons-io:commons-io:2.6'

Gradle Kotlin DSL

implementation("commons-io:commons-io:2.6")

其他人# EYZ0

只是一个基于正则表达式的替代方案。没那么快,也没那么好。

Pattern pattern = Pattern.compile("\\.([^.]*)$");
Matcher matcher = pattern.matcher(fileName);


if (matcher.find()) {
String ext = matcher.group(1);
}

为了考虑没有之前字符的文件名,你必须使用接受答案的轻微变化:

String extension = "";


int i = fileName.lastIndexOf('.');
if (i >= 0) {
extension = fileName.substring(i+1);
}

"file.doc" => "doc"
"file.doc.gz" => "gz"
".doc" => "doc"

Java有一个内置的方法来处理这个问题,在java.nio.file.Files类中,这可能适合你的需要:

File f = new File("/path/to/file/foo.txt");
String ext = Files.probeContentType(f.toPath());
if(ext.equalsIgnoreCase("txt")) do whatever;

注意,这个静态方法使用规范在这里找到来检索“内容类型”,它可以变化。

private String getFileExtension(File file) {
String name = file.getName();
int lastIndexOf = name.lastIndexOf(".");
if (lastIndexOf == -1) {
return ""; // empty extension
}
return name.substring(lastIndexOf);
}

我的肮脏和可能最小的使用String.replaceAll:

.replaceAll("^.*\\.(.*)$", "$1")

请注意,第一个*是贪婪的,所以它将尽可能抓取大多数可能的字符,然后只剩下最后一个点和文件扩展名。

如果你计划使用Apache common -io,只是想检查文件的扩展名,然后做一些操作,你可以使用,这里是一个片段:

if(FilenameUtils.isExtension(file.getName(),"java")) {
someoperation();
}

如果在Android上,你可以使用这个:

String ext = android.webkit.MimeTypeMap.getFileExtensionFromUrl(file.getName());
String extension = com.google.common.io.Files.getFileExtension("fileName.jpg");

在这里我做了一个小方法(然而不是那么安全,并没有检查很多错误),但如果只有你在编写一个普通的java程序,这就足够找到文件类型了。这对于复杂的文件类型并不适用,但这些文件类型通常不常用。

    public static String getFileType(String path){
String fileType = null;
fileType = path.substring(path.indexOf('.',path.lastIndexOf('/'))+1).toUpperCase();
return fileType;
}

这是一种经过测试的方法

public static String getExtension(String fileName) {
char ch;
int len;
if(fileName==null ||
(len = fileName.length())==0 ||
(ch = fileName.charAt(len-1))=='/' || ch=='\\' || //in the case of a directory
ch=='.' ) //in the case of . or ..
return "";
int dotInd = fileName.lastIndexOf('.'),
sepInd = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));
if( dotInd<=sepInd )
return "";
else
return fileName.substring(dotInd+1).toLowerCase();
}

测试用例:

@Test
public void testGetExtension() {
assertEquals("", getExtension("C"));
assertEquals("ext", getExtension("C.ext"));
assertEquals("ext", getExtension("A/B/C.ext"));
assertEquals("", getExtension("A/B/C.ext/"));
assertEquals("", getExtension("A/B/C.ext/.."));
assertEquals("bin", getExtension("A/B/C.bin"));
assertEquals("hidden", getExtension(".hidden"));
assertEquals("dsstore", getExtension("/user/home/.dsstore"));
assertEquals("", getExtension(".strange."));
assertEquals("3", getExtension("1.2.3"));
assertEquals("exe", getExtension("C:\\Program Files (x86)\\java\\bin\\javaw.exe"));
}

这个特别的问题给了我很多麻烦,然后我找到了一个非常简单的解决方案,我张贴在这里。

file.getName().toLowerCase().endsWith(".txt");

就是这样。

从文件名获取文件扩展名

/**
* The extension separator character.
*/
private static final char EXTENSION_SEPARATOR = '.';


/**
* The Unix separator character.
*/
private static final char UNIX_SEPARATOR = '/';


/**
* The Windows separator character.
*/
private static final char WINDOWS_SEPARATOR = '\\';


/**
* The system separator character.
*/
private static final char SYSTEM_SEPARATOR = File.separatorChar;


/**
* Gets the extension of a filename.
* <p>
* This method returns the textual part of the filename after the last dot.
* There must be no directory separator after the dot.
* <pre>
* foo.txt      --> "txt"
* a/b/c.jpg    --> "jpg"
* a/b.txt/c    --> ""
* a/b/c        --> ""
* </pre>
* <p>
* The output will be the same irrespective of the machine that the code is running on.
*
* @param filename the filename to retrieve the extension of.
* @return the extension of the file or an empty string if none exists.
*/
public static String getExtension(String filename) {
if (filename == null) {
return null;
}
int index = indexOfExtension(filename);
if (index == -1) {
return "";
} else {
return filename.substring(index + 1);
}
}


/**
* Returns the index of the last extension separator character, which is a dot.
* <p>
* This method also checks that there is no directory separator after the last dot.
* To do this it uses {@link #indexOfLastSeparator(String)} which will
* handle a file in either Unix or Windows format.
* <p>
* The output will be the same irrespective of the machine that the code is running on.
*
* @param filename  the filename to find the last path separator in, null returns -1
* @return the index of the last separator character, or -1 if there
* is no such character
*/
public static int indexOfExtension(String filename) {
if (filename == null) {
return -1;
}
int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);
int lastSeparator = indexOfLastSeparator(filename);
return (lastSeparator > extensionPos ? -1 : extensionPos);
}


/**
* Returns the index of the last directory separator character.
* <p>
* This method will handle a file in either Unix or Windows format.
* The position of the last forward or backslash is returned.
* <p>
* The output will be the same irrespective of the machine that the code is running on.
*
* @param filename  the filename to find the last path separator in, null returns -1
* @return the index of the last separator character, or -1 if there
* is no such character
*/
public static int indexOfLastSeparator(String filename) {
if (filename == null) {
return -1;
}
int lastUnixPos = filename.lastIndexOf(UNIX_SEPARATOR);
int lastWindowsPos = filename.lastIndexOf(WINDOWS_SEPARATOR);
return Math.max(lastUnixPos, lastWindowsPos);
}

学分

  1. 复制自Apache FileNameUtils类- http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/1.3.2/org/apache/commons/io/FilenameUtils.java#FilenameUtils.getExtension%28java.lang.String%29

正则表达式版本怎么样:

static final Pattern PATTERN = Pattern.compile("(.*)\\.(.*)");


Matcher m = PATTERN.matcher(path);
if (m.find()) {
System.out.println("File path/name: " + m.group(1));
System.out.println("Extention: " + m.group(2));
}

或者支持空扩展名:

static final Pattern PATTERN =
Pattern.compile("((.*\\" + File.separator + ")?(.*)(\\.(.*)))|(.*\\" + File.separator + ")?(.*)");


class Separated {
String path, name, ext;
}


Separated parsePath(String path) {
Separated res = new Separated();
Matcher m = PATTERN.matcher(path);
if (m.find()) {
if (m.group(1) != null) {
res.path = m.group(2);
res.name = m.group(3);
res.ext = m.group(5);
} else {
res.path = m.group(6);
res.name = m.group(7);
}
}
return res;
}




Separated sp = parsePath("/root/docs/readme.txt");
System.out.println("path: " + sp.path);
System.out.println("name: " + sp.name);
System.out.println("Extention: " + sp.ext);

result for *nix:
< em >路径:/root/docs/ < br > 名称:自述< br > 延伸:txt < / em > < / p >

for windows, parsePath("c:\windows\readme.txt"):
< em >路径:c: \ windows \ < br > 名称:自述< br > 延伸:txt < / em > < / p >

下面是返回值为Optional的版本(因为你不能确定文件有扩展名)…还有健全检查…

import java.io.File;
import java.util.Optional;


public class GetFileExtensionTool {


public static Optional<String> getFileExtension(File file) {
if (file == null) {
throw new NullPointerException("file argument was null");
}
if (!file.isFile()) {
throw new IllegalArgumentException("getFileExtension(File file)"
+ " called on File object that wasn't an actual file"
+ " (perhaps a directory or device?). file had path: "
+ file.getAbsolutePath());
}
String fileName = file.getName();
int i = fileName.lastIndexOf('.');
if (i > 0) {
return Optional.of(fileName.substring(i + 1));
} else {
return Optional.empty();
}
}
}

在不使用任何库的情况下,你可以使用String方法,如下所示:

        String[] splits = fileNames.get(i).split("\\.");


String extension = "";


if(splits.length >= 2)
{
extension = splits[splits.length-1];
}
String path = "/Users/test/test.txt";
String extension = "";


if (path.contains("."))
extension = path.substring(path.lastIndexOf("."));

返回. txt”

如果你只想要“txt”,设置为path.lastIndexOf(".") + 1

试试这个。

String[] extension = "adadad.adad.adnandad.jpg".split("\\.(?=[^\\.]+$)"); // ['adadad.adad.adnandad','jpg']
extension[1] // jpg
  @Test
public void getFileExtension(String fileName){
String extension = null;
List<String> list = new ArrayList<>();
do{
extension =  FilenameUtils.getExtension(fileName);
if(extension==null){
break;
}
if(!extension.isEmpty()){
list.add("."+extension);
}
fileName = FilenameUtils.getBaseName(fileName);
}while (!extension.isEmpty());
Collections.reverse(list);
System.out.println(list.toString());
}

我发现了一个更好的方法来找到扩展混合以上所有的答案

public static String getFileExtension(String fileLink) {


String extension;
Uri uri = Uri.parse(fileLink);
String scheme = uri.getScheme();
if (scheme != null && scheme.equals(ContentResolver.SCHEME_CONTENT)) {
MimeTypeMap mime = MimeTypeMap.getSingleton();
extension = mime.getExtensionFromMimeType(CoreApp.getInstance().getContentResolver().getType(uri));
} else {
extension = MimeTypeMap.getFileExtensionFromUrl(fileLink);
}


return extension;
}


public static String getMimeType(String fileLink) {
String type = CoreApp.getInstance().getContentResolver().getType(Uri.parse(fileLink));
if (!TextUtils.isEmpty(type)) return type;
MimeTypeMap mime = MimeTypeMap.getSingleton();
return mime.getMimeTypeFromExtension(FileChooserUtil.getFileExtension(fileLink));
}

从所有其他答案中可以明显看出,没有足够的“内置”函数。这是一种安全简单的方法。

String getFileExtension(File file) {
if (file == null) {
return "";
}
String name = file.getName();
int i = name.lastIndexOf('.');
String ext = i > 0 ? name.substring(i + 1) : "";
return ext;
}

我喜欢幽灵的回答的简单性,在他的一个评论中有一个链接到另一个问题EboMike制造的答案,它修复了文件路径中的点。

在不实现某种第三方API的情况下,我建议:

private String getFileExtension(File file) {


String name = file.getName().substring(Math.max(file.getName().lastIndexOf('/'),
file.getName().lastIndexOf('\\')) < 0 ? 0 : Math.max(file.getName().lastIndexOf('/'),
file.getName().lastIndexOf('\\')));
int lastIndexOf = name.lastIndexOf(".");
if (lastIndexOf == -1) {
return ""; // empty extension
}
return name.substring(lastIndexOf + 1); // doesn't return "." with extension
}

类似这样的东西在任何ImageIO的write方法中可能很有用,其中必须传入文件格式。

既然可以自己动手,为什么还要使用整个第三方API呢?

下面是Java 8的另一个一行程序。

String ext = Arrays.stream(fileName.split("\\.")).reduce((a,b) -> b).orElse(null)

其工作原理如下:

  1. 使用"."将字符串拆分为字符串数组。
  2. 将数组转换为流
  3. 使用reduce获取流的最后一个元素,即文件扩展名

如果你在项目中使用Spring框架,那么你可以使用stringutil

import org.springframework.util.StringUtils;


StringUtils.getFilenameExtension("YourFileName")
    private String getExtension(File file)
{
String fileName = file.getName();
String[] ext = fileName.split("\\.");
return ext[ext.length -1];
}

流利的方式:

public static String fileExtension(String fileName) {
return Optional.of(fileName.lastIndexOf(".")).filter(i-> i >= 0)
.filter(i-> i > fileName.lastIndexOf(File.separator))
.map(fileName::substring).orElse("");
}

Java 20 EA

从Java 20 EA(早期访问)开始,终于有了一个新方法Path#getExtension,它将扩展名返回为String:

Paths.get("/Users/admin/notes.txt").getExtension();              // "txt"
Paths.get("/Users/admin/.gitconfig").getExtension();             // "gitconfig"
Paths.get("/Users/admin/configuration.xml.zip").getExtension();  // "zip"
Paths.get("/Users/admin/file").getExtension();                   // null