在 Java 中删除文件扩展名

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3449218/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 00:53:19  来源:igfitidea点击:

Remove filename extension in Java

javafile-extension

提问by hpique

(Without including any external libraries.)

(不包括任何外部库。)

What's the most efficient way to remove the extension of a filename in Java, without assuming anything of the filename?

在不假设任何文件名的情况下,在 Java 中删除文件名扩展名的最有效方法是什么?

Some examples and expected results:

一些示例和预期结果:

  • folder > folder
  • hello.txt > hello
  • read.me > read
  • hello.bkp.txt > hello.bkp
  • weird..name > weird.
  • .hidden > .hidden
  • 文件夹 > 文件夹
  • 你好.txt > 你好
  • 阅读我 > 阅读
  • 你好.bkp.txt > 你好.bkp
  • 奇怪的..名字 > 奇怪的。
  • .隐藏 > .隐藏

(or should the last one be just hidden?)

(还是应该隐藏最后一个?)

Edit: The original question assumed that the input is a filename (not a file path). Since some answers are talking about file paths, such functions should also work in cases like:

编辑:最初的问题假设输入是文件名(不是文件路径)。由于某些答案涉及文件路径,因此此类功能也应适用于以下情况:

  • rare.folder/hello > rare.folder/hello
  • 稀有.文件夹/你好 > 稀有.文件夹/你好

This particular case is handled very well by Sylvain M's answer.

Sylvain M 的回答很好地处理了这种特殊情况。

采纳答案by Andrzej Doyle

I'm going to have a stab at this that uses the two-arg version of lastIndexOfin order to remove some special-case checking code, and hopefully make the intention more readable. Credit goes to Justin 'jinguy' Nelsonfor providing the basis of this method:

我将尝试使用两个参数版本的lastIndexOf,以删除一些特殊情况检查代码,并希望使意图更具可读性。幸得贾斯汀“jinguy”尼尔森提供这种方法的基础:

public static String removeExtention(String filePath) {
    // These first few lines the same as Justin's
    File f = new File(filePath);

    // if it's a directory, don't remove the extention
    if (f.isDirectory()) return filePath;

    String name = f.getName();

    // Now we know it's a file - don't need to do any special hidden
    // checking or contains() checking because of:
    final int lastPeriodPos = name.lastIndexOf('.');
    if (lastPeriodPos <= 0)
    {
        // No period after first character - return name as it was passed in
        return filePath;
    }
    else
    {
        // Remove the last period and everything after it
        File renamed = new File(f.getParent(), name.substring(0, lastPeriodPos));
        return renamed.getPath();
    }
}

To me this is clearer than special-casing hidden files and files that don't contain a dot. It also reads clearer to what I understand your specification to be; something like "remove the last dot and everything following it, assuming it exists and is not the first character of the filename".

对我来说,这比特殊的隐藏文件和不包含点的文件更清楚。它也更清楚地了解我对您的规范的理解;类似于“删除最后一个点及其后面的所有内容,假设它存在并且不是文件名的第一个字符”。

Note that this example also implies Strings as inputs and outputs. Since most of the abstraction requires Fileobjects, it would be marginally clearer if those were the inputs and outputs as well.

请注意,此示例还暗示字符串作为输入和输出。由于大多数抽象都需要File对象,如果这些对象也是输入和输出,那么它会稍微清晰一些。

回答by jjnguy

This will take a file path and then return the new name of the file without the extension.

这将采用文件路径,然后返回不带扩展名的文件的新名称。

public static String removeExtention(String filePath) {
    File f = new File(filePath);
    // if it's a directory, don't remove the extention
    if (fisDirectory()) return f.getName();
    String name = f.getName();
    // if it is a hidden file
    if (name.startsWith(".")) {
        // if there is no extn, do not rmove one...
        if (name.lastIndexOf('.') == name.indexOf('.')) return name;
    }
    // if there is no extention, don't do anything
    if (!name.contains(".") return name;
    // Otherwise, remove the last 'extension type thing'
    return name.substring(0, name.lastIndexOf('.'))
}

People should note that this was written on my netbook, in the tiny SO editor box. This code is not meant for production. It is only meant to server as a good first attempt example of how I would go about removing the extension from a filename.

人们应该注意到这是写在我的上网本上,在小小的 SO 编辑器框中。此代码不适用于生产。它只是作为一个很好的第一次尝试示例来服务,我将如何从文件名中删除扩展名。

回答by sly7_7

Using common io from apache http://commons.apache.org/io/

使用来自 apache http://commons.apache.org/io/ 的通用 io

public static String removeExtension(String filename)

公共静态字符串removeExtension(字符串文件名)

FYI, the source code is here:

仅供参考,源代码在这里:

http://commons.apache.org/proper/commons-io/javadocs/api-release/src-html/org/apache/commons/io/FilenameUtils.html#line.1025

http://commons.apache.org/proper/commons-io/javadocs/api-release/src-html/org/apache/commons/io/FilenameUtils.html#line.1025

Arg, I've just tried something...

Arg,我刚刚尝试了一些东西......

System.out.println(FilenameUtils.getExtension(".polop")); // polop
System.out.println(FilenameUtils.removeExtension(".polop")); // empty string

So, this solution seems to be not very good... Even with common io, you'll have to play with removeExtension() getExtension() indexOfExtension()...

所以,这个解决方案似乎不是很好......即使使用普通io,你也必须使用removeExtension() getExtension() indexOfExtension() ...

回答by ShinTakezou

Regex for these things are "fast" enough but not efficient if compared to the simplest method that can be thought: scan the string from the end and truncate it at the first dot (not inclusive). In Java you could use lastIndexOf and substring to take only the part you are interested in. The initial dot should be considered as a special case and if the last occurrence of "." is at the beginning, the whole string should be returned.

如果与可以想到的最简单的方法相比,这些事情的正则表达式足够“快”但效率不高:从末尾扫描字符串并在第一个点(不包括)截断它。在 Java 中,您可以使用 lastIndexOf 和 substring 来仅获取您感兴趣的部分。最初的点应该被视为一种特殊情况,如果最后一次出现“.”。在开头,应该返回整个字符串。

回答by LatinSuD

I know a regex to do it, but in Java do i have to write like 10 lines of code to do a simple regex substitution?

我知道一个正则表达式可以做到这一点,但是在 Java 中我是否必须编写 10 行代码来执行简单的正则表达式替换?

With and without killing hidden files:

有和没有杀死隐藏文件:

^(.*)\..*$
^(..*)\..*$

回答by William Niu

filename.replace("$(.+)\.\w+", "");

回答by DJClayworth

It's actually very easy, assuming that you have a valid filename.

假设您有一个有效的文件名,这实际上非常简单。

In Windows filenames the dot character is only used to designate an extension. So strip off the dot and anything after it.

在 Windows 文件名中,点字符仅用于指定扩展名。所以去掉点和它后面的任何东西。

In unix-like filenames the dot indicates an extension if it's after the last separator ('/') and has at least one character between it and the last separator (and is not the first character, if there are no separators). Find the last dot, see if it satisfies the conditions, and strip it and any trailing characters if it does.

在类 Unix 文件名中,如果点位于最后一个分隔符 ('/') 之后并且在它和最后一个分隔符之间至少有一个字符(如果没有分隔符,则不是第一个字符),则该点表示扩展名。找到最后一个点,看看它是否满足条件,如果满足则去掉它和任何尾随字符。

It's important that you validate the filename before you do this, as this algorithm on an invlaid filename might do something unexpected and generate a valid filename. So in Windows you may need to check that there isn't a backslash, or a colon, after the dot.

在执行此操作之前验证文件名很重要,因为此算法对 invlaid 文件名可能会做一些意想不到的事情并生成有效的文件名。因此,在 Windows 中,您可能需要检查点后是否没有反斜杠或冒号。

If you don't know what kind of filename you are dealing with, treating them all like Unix will get you most of the way.

如果你不知道你正在处理什么样的文件名,像 Unix 一样对待它们会让你大获全胜。

回答by Janek Bogucki

Use new Remover().remove(String),

使用 new Remover().remove(String),

jdb@Vigor14:/tmp/stackoverflow> javac Remover.java && java Remover
folder > folder
hello.txt > hello
read.me > read
hello.bkp.txt > hello.bkp
weird..name > weird.
.hidden > .hidden

Remover.java,

卸妆.java,

import java.util.*;

public class Remover {

    public static void main(String [] args){
        Map<String, String> tests = new LinkedHashMap<String, String>();
        tests.put("folder", "folder");
        tests.put("hello.txt", "hello");
        tests.put("read.me", "read");
        tests.put("hello.bkp.txt", "hello.bkp");
        tests.put("weird..name", "weird.");
        tests.put(".hidden", ".hidden");

        Remover r = new Remover();
        for(String in: tests.keySet()){
            String actual = r.remove(in);
            log(in+" > " +actual);
            String expected = tests.get(in);
            if(!expected.equals(actual)){
                throw new RuntimeException();
            }
        }
    }

    private static void log(String s){
        System.out.println(s);
    }

    public String remove(String in){
        if(in == null) {
            return null;
        }
        int p = in.lastIndexOf(".");
        if(p <= 0){
            return in;
        }
        return in.substring(0, p);
    }
}

回答by Jay

int p=name.lastIndexOf('.');
if (p>0)
  name=name.substring(0,p);

I said "p>0" instead of "p>=0" because if the first character is a period we presumably do not want to wipe out the entire name, as in your ".hidden" example.

我说“p>0”而不是“p>=0”,因为如果第一个字符是句点,我们大概不想像你的“.hidden”示例中那样删除整个名称。

Do you want to actually update the file name on the disk or are you talking about just manipulating it internally?

您是要实际更新磁盘上的文件名还是只是在内部操作它?

回答by oldnemesis

The remove()function above should be rewritten to support test cases like LOST.DIR/myfile.txt

remove()上面的函数应该被重写以支持测试用例,比如LOST.DIR/myfile.txt

    public static String removeExtension( String in )
{
    int p = in.lastIndexOf(".");
    if ( p < 0 )
        return in;

    int d = in.lastIndexOf( File.separator );

    if ( d < 0 && p == 0 )
        return in;

    if ( d >= 0 && d > p )
        return in;

    return in.substring( 0, p );
}