删除Java中的文件扩展名

(不包括任何外部库。)

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

一些例子和预期结果:

  • 文件夹>文件夹
  • hello.txt>你好
  • read.me>阅读
  • hello.bkp.txt> hello.bkp
  • 奇怪……名字>奇怪。
  • .hidden> .hidden

(或者应该隐藏最后一个?)

编辑 :原始问题假设输入是文件名(不是文件路径)。 由于一些答案是关于文件路径,因此这些函数也应该适用于以下情况:

  • rare.folder / hello> rare.folder / hello

Sylvain M的答案很好地处理了这个特例。

我将要使用lastIndexOf -index的两个arg版本来删除一些特殊情况检查代码,并希望使意图更具可读性。 感谢Justin’jinguy’Nelson提供此方法的基础:

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

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

请注意,此示例还将字符串作为输入和输出。 由于大部分抽象都需要File对象,因此如果那些是输入和输出,那么它将更加清晰。

使用apache中的常用io http://commons.apache.org/io/

public static String removeExtension(String filename)

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

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

Arg,我刚试了一下……

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

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

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

 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('.')) } 

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

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

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

在类似unix的文件名中,如果点在最后一个分隔符(’/’)之后并且在它和最后一个分隔符之间至少有一个字符(并且不是第一个字符,如果没有分隔符),则点表示扩展名。 找到最后一个点,查看它是否满足条件,并删除它和任何尾随字符(如果有)。

在执行此操作之前validation文件名非常重要,因为此算法在invlaid文件名上可能会执行一些意外操作并生成有效的文件名。 因此在Windows中,您可能需要检查点后面没有反斜杠或冒号。

如果你不知道你正在处理什么样的文件名,那么像Unix一样对待它们将会让你大部分时间。

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

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

您是否想要实际更新磁盘上的文件名,或者您是在谈论内部操作它?

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

我知道一个正则表达式,但在Java中,我必须编写10行代码来进行简单的正则表达式替换吗?

有和没有杀死隐藏文件:

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

使用新的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,

 import java.util.*; public class Remover { public static void main(String [] args){ Map tests = new LinkedHashMap(); 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); } } 
 filename.replace("$(.+)\.\\w+", "\1"); 

应重写上面的remove()函数以支持LOST.DIR/myfile.txtLOST.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 ); }