195

What's the most efficient way to trim the suffix in Java, like this:

title part1.txt
title part2.html
=>
title part1
title part2
Michael Myers
  • 188,989
  • 46
  • 291
  • 292
omg
  • 136,412
  • 142
  • 288
  • 348

23 Answers23

316

This is the sort of code that we shouldn't be doing ourselves. Use libraries for the mundane stuff, save your brain for the hard stuff.

In this case, I recommend using FilenameUtils.removeExtension() from Apache Commons IO

skaffman
  • 398,947
  • 96
  • 818
  • 769
  • 7
    For 95% of the projects, this should be the accepted answer. Rewriting code like this is the root cause for many headaches! – Carsten Hoffmann Aug 01 '16 at 14:19
  • 1
    Just add the following line in gradle to add the depedency:- compile 'commons-io:commons-io:2.6' – Deepak Sharma Dec 21 '17 at 14:50
  • 17
    If you have Apache Commons I/O already in your project, that's right. But if this all you need from it, you're adding (at least) 2.5 MB of dead weight to your project for something that can be easily done with a single line. – foo Sep 03 '18 at 09:40
  • Good luck doing it in a single line so that it succeeds on even the obvious edge cases – Steve Bosman Apr 06 '22 at 10:29
  • heads-up that this won't work if the file has two extensions ie. filename.csv.zip – gzp___ Apr 19 '22 at 14:24
257
str.substring(0, str.lastIndexOf('.'))
Sunny Milenov
  • 21,990
  • 6
  • 80
  • 106
Svitlana Maksymchuk
  • 4,330
  • 2
  • 16
  • 11
94

As using the String.substring and String.lastIndex in a one-liner is good, there are some issues in terms of being able to cope with certain file paths.

Take for example the following path:

a.b/c

Using the one-liner will result in:

a

That's incorrect.

The result should have been c, but since the file lacked an extension, but the path had a directory with a . in the name, the one-liner method was tricked into giving part of the path as the filename, which is not correct.

Need for checks

Inspired by skaffman's answer, I took a look at the FilenameUtils.removeExtension method of the Apache Commons IO.

In order to recreate its behavior, I wrote a few tests the new method should fulfill, which are the following:

Path                  Filename
--------------        --------
a/b/c                 c
a/b/c.jpg             c
a/b/c.jpg.jpg         c.jpg

a.b/c                 c
a.b/c.jpg             c
a.b/c.jpg.jpg         c.jpg

c                     c
c.jpg                 c
c.jpg.jpg             c.jpg

(And that's all I've checked for -- there probably are other checks that should be in place that I've overlooked.)

The implementation

The following is my implementation for the removeExtension method:

public static String removeExtension(String s) {

    String separator = System.getProperty("file.separator");
    String filename;

    // Remove the path upto the filename.
    int lastSeparatorIndex = s.lastIndexOf(separator);
    if (lastSeparatorIndex == -1) {
        filename = s;
    } else {
        filename = s.substring(lastSeparatorIndex + 1);
    }

    // Remove the extension.
    int extensionIndex = filename.lastIndexOf(".");
    if (extensionIndex == -1)
        return filename;

    return filename.substring(0, extensionIndex);
}

Running this removeExtension method with the above tests yield the results listed above.

The method was tested with the following code. As this was run on Windows, the path separator is a \ which must be escaped with a \ when used as part of a String literal.

System.out.println(removeExtension("a\\b\\c"));
System.out.println(removeExtension("a\\b\\c.jpg"));
System.out.println(removeExtension("a\\b\\c.jpg.jpg"));

System.out.println(removeExtension("a.b\\c"));
System.out.println(removeExtension("a.b\\c.jpg"));
System.out.println(removeExtension("a.b\\c.jpg.jpg"));

System.out.println(removeExtension("c"));
System.out.println(removeExtension("c.jpg"));
System.out.println(removeExtension("c.jpg.jpg"));

The results were:

c
c
c.jpg
c
c
c.jpg
c
c
c.jpg

The results are the desired results outlined in the test the method should fulfill.

Community
  • 1
  • 1
coobird
  • 159,216
  • 35
  • 211
  • 226
  • 4
    Great answer. Is there a particular reason why you use `System.getProperty("file.separator")` and not just `File.separator`? – halirutan Sep 04 '13 at 22:10
  • 2
    A word of warning: This solution also removes the preceding path, not just the extension, unlike the Apache Commons IO method. – DHa Apr 21 '16 at 22:34
  • 3
    It appears this will fail for the `/path/to/.htaccess` – Kuzeko May 04 '16 at 15:22
19

BTW, in my case, when I wanted a quick solution to remove a specific extension, this is approximately what I did:

  if (filename.endsWith(ext))
    return filename.substring(0,filename.length() - ext.length());
  else
    return filename;
Hartmut Pfitzinger
  • 2,304
  • 3
  • 28
  • 48
Edward Falk
  • 9,991
  • 11
  • 77
  • 112
19
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));
Jherico
  • 28,584
  • 8
  • 61
  • 87
11

you can try this function , very basic

public String getWithoutExtension(String fileFullPath){
    return fileFullPath.substring(0, fileFullPath.lastIndexOf('.'));
}
Shantonu
  • 1,280
  • 13
  • 12
10

Use a method in com.google.common.io.Files class if your project is already dependent on Google core library. The method you need is getNameWithoutExtension.

Toby
  • 387
  • 1
  • 4
  • 8
  • Why someone is against my answer?? – Toby Jan 09 '18 at 02:19
  • Note that this returns the base name only, so the path is also removed: https://google.github.io/guava/releases/19.0/api/docs/com/google/common/io/Files.html#getNameWithoutExtension(java.lang.String) – thSoft Jul 02 '18 at 16:09
9
String fileName="foo.bar";
int dotIndex=fileName.lastIndexOf('.');
if(dotIndex>=0) { // to prevent exception if there is no dot
  fileName=fileName.substring(0,dotIndex);
}

Is this a trick question? :p

I can't think of a faster way atm.

Huxi
  • 4,242
  • 3
  • 33
  • 31
5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();
Alexander
  • 83
  • 1
  • 1
  • 3
    Opposite of what was asked and there is no need to pass the length, just use one arg substring –  Oct 19 '13 at 14:48
5

I found coolbird's answer particularly useful.

But I changed the last result statements to:

if (extensionIndex == -1)
  return s;

return s.substring(0, lastSeparatorIndex+1) 
         + filename.substring(0, extensionIndex);

as I wanted the full path name to be returned.

So "C:\Users\mroh004.COM\Documents\Test\Test.xml" becomes 
   "C:\Users\mroh004.COM\Documents\Test\Test" and not
   "Test"
Community
  • 1
  • 1
mxro
  • 6,588
  • 4
  • 35
  • 38
4

Use a regex. This one replaces the last dot, and everything after it.

String baseName = fileName.replaceAll("\\.[^.]*$", "");

You can also create a Pattern object if you want to precompile the regex.

Steven Spungin
  • 27,002
  • 5
  • 88
  • 78
4

If you use Spring you could use

org.springframework.util.StringUtils.stripFilenameExtension(String path)

Strip the filename extension from the given Java resource path, e.g.

"mypath/myfile.txt" -> "mypath/myfile".

Params: path – the file path

Returns: the path with stripped filename extension

Wolf359
  • 2,620
  • 4
  • 42
  • 62
  • Thank you for posting. For some reason, these SO posts always have an aversion to using libraries, but my project already has spring dependency and this is much more explicit and clean than writing myself – Adam Hughes Aug 09 '21 at 15:38
2
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }
supernova
  • 3,111
  • 4
  • 33
  • 30
1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");
Mahdak
  • 111
  • 1
  • 1
  • 5
1

create a new file with string image path

String imagePath;
File test = new File(imagePath);
test.getName();
test.getPath();
getExtension(test.getName());


public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }
Pravin Bhosale
  • 1,920
  • 19
  • 14
1

org.apache.commons.io.FilenameUtils version 2.4 gives the following answer

public static String removeExtension(String filename) {
    if (filename == null) {
        return null;
    }
    int index = indexOfExtension(filename);
    if (index == -1) {
        return filename;
    } else {
        return filename.substring(0, index);
    }
}

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

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

public static final char EXTENSION_SEPARATOR = '.';
private static final char UNIX_SEPARATOR = '/';
private static final char WINDOWS_SEPARATOR = '\\';
Someone Somewhere
  • 23,475
  • 11
  • 118
  • 166
1

The best what I can write trying to stick to the Path class:

Path removeExtension(Path path) {
    return path.resolveSibling(path.getFileName().toString().replaceFirst("\\.[^.]*$", ""));
}
David L.
  • 3,149
  • 2
  • 26
  • 28
1

dont do stress on mind guys. i did already many times. just copy paste this public static method in your staticUtils library for future uses ;-)

static String removeExtension(String path){
        String filename;
        String foldrpath;
        String filenameWithoutExtension;
        if(path.equals("")){return "";}
        if(path.contains("\\")){    // direct substring method give wrong result for "a.b.c.d\e.f.g\supersu"
            filename = path.substring(path.lastIndexOf("\\"));
            foldrpath = path.substring(0, path.lastIndexOf('\\'));;
            if(filename.contains(".")){
                filenameWithoutExtension = filename.substring(0, filename.lastIndexOf('.'));
            }else{
                filenameWithoutExtension = filename;
            }
            return foldrpath + filenameWithoutExtension;
        }else{
            return path.substring(0, path.lastIndexOf('.'));
        }
    }
MbPCM
  • 457
  • 5
  • 12
0

Keeping in mind the scenarios where there is no file extension or there is more than one file extension

example Filename : file | file.txt | file.tar.bz2

/**
 *
 * @param fileName
 * @return file extension
 * example file.fastq.gz => fastq.gz
 */
private String extractFileExtension(String fileName) {
    String type = "undefined";
    if (FilenameUtils.indexOfExtension(fileName) != -1) {
        String fileBaseName = FilenameUtils.getBaseName(fileName);
        int indexOfExtension = -1;
        while (fileBaseName.contains(".")) {
            indexOfExtension = FilenameUtils.indexOfExtension(fileBaseName);
            fileBaseName = FilenameUtils.getBaseName(fileBaseName);
        }
        type = fileName.substring(indexOfExtension + 1, fileName.length());
    }
    return type;
}
Choesang
  • 1,225
  • 1
  • 14
  • 23
0
String img = "example.jpg";
// String imgLink = "http://www.example.com/example.jpg";
URI uri = null;

try {
    uri = new URI(img);
    String[] segments = uri.getPath().split("/");
    System.out.println(segments[segments.length-1].split("\\.")[0]);
} catch (Exception e) {
    e.printStackTrace();
}

This will output example for both img and imgLink

urs86ro
  • 99
  • 1
  • 3
0
private String trimFileName(String fileName)
    {
        String[] ext;
        ext = fileName.split("\\.");
        
        return fileName.replace(ext[ext.length - 1], "");

    }

This code will spilt the file name into parts where ever it has " . ", For eg. If the file name is file-name.hello.txt then it will be spilted into string array as , { "file-name", "hello", "txt" }. So anyhow the last element in this string array will be the file extension of that particular file , so we can simply find the last element of any arrays with arrayname.length - 1, so after we get to know the last element, we can just replace the file extension with an empty string in that file name. Finally this will return file-name.hello. , if you want to remove also the last period then you can add the string with only period to the last element of string array in the return line. Which should look like,

return fileName.replace("." +  ext[ext.length - 1], "");
  • A few words explaing how this code is supposed to help would be really useful – Vega Aug 08 '21 at 15:30
  • This will give an unexpected result for an input like `file-doc-new.marketing.doc`, as it will remove both instances of the word `doc`. – Mike K Mar 06 '23 at 18:56
0

I would do like this:

String title_part = "title part1.txt";
int i;
for(i=title_part.length()-1 ; i>=0 && title_part.charAt(i)!='.' ; i--);
title_part = title_part.substring(0,i);

Starting to the end till the '.' then call substring.

Edit: Might not be a golf but it's effective :)

Shashi
  • 746
  • 10
  • 39
fmsf
  • 36,317
  • 49
  • 147
  • 195
-1
public static String removeExtension(String file) {
    if(file != null && file.length() > 0) {
        while(file.contains(".")) {
            file = file.substring(0, file.lastIndexOf('.'));
        }
    }
    return file;
}
Alexey
  • 119
  • 1
  • 2
  • 8
  • This will transform "a.jpg.jpg" to "a" instead of the (correct) "a.jpg". What purpose serves the `file.length() > 0` check? – Klaus Gütter Jan 12 '19 at 06:17
  • Main question was "how remove extension ?", so yes its transform "a.txt.zip" to "a" and ".htaccess" to emptiness. This function work with Strings, so file names can be not null but still can be 0 length, faster check if it worth it before parsing symbols. Regards. – Alexey Jan 12 '19 at 14:37