[java] How to get the filename without the extension in Java?

Can anyone tell me how to get the filename without the extension? Example:

fileNameWithExt = "test.xml";
fileNameWithOutExt = "test";

This question is related to java file

The answer is


My solution needs the following import.

import java.io.File;

The following method should return the desired output string:

private static String getFilenameWithoutExtension(File file) throws IOException {
    String filename = file.getCanonicalPath();
    String filenameWithoutExtension;
    if (filename.contains("."))
        filenameWithoutExtension = filename.substring(filename.lastIndexOf(System.getProperty("file.separator"))+1, filename.lastIndexOf('.'));
    else
        filenameWithoutExtension = filename.substring(filename.lastIndexOf(System.getProperty("file.separator"))+1);

    return filenameWithoutExtension;
}

public static String getFileExtension(String fileName) {
        if (TextUtils.isEmpty(fileName) || !fileName.contains(".") || fileName.endsWith(".")) return null;
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }

    public static String getBaseFileName(String fileName) {
        if (TextUtils.isEmpty(fileName) || !fileName.contains(".") || fileName.endsWith(".")) return null;
        return fileName.substring(0,fileName.lastIndexOf("."));
    }

Here is the consolidated list order by my preference.

Using apache commons

import org.apache.commons.io.FilenameUtils;

String fileNameWithoutExt = FilenameUtils.getBaseName(fileName);
                          
                           OR

String fileNameWithOutExt = FilenameUtils.removeExtension(fileName);

Using Google Guava (If u already using it)

import com.google.common.io.Files;
String fileNameWithOutExt = Files.getNameWithoutExtension(fileName);

Files.getNameWithoutExtension

Or using Core Java

1)

String fileName = file.getName();
int pos = fileName.lastIndexOf(".");
if (pos > 0 && pos < (fileName.length() - 1)) { // If '.' is not the first or last character.
    fileName = fileName.substring(0, pos);
}
if (fileName.indexOf(".") > 0) {
   return fileName.substring(0, fileName.lastIndexOf("."));
} else {
   return fileName;
}
private static final Pattern ext = Pattern.compile("(?<=.)\\.[^.]+$");

public static String getFileNameWithoutExtension(File file) {
    return ext.matcher(file.getName()).replaceAll("");
}

Liferay API

import com.liferay.portal.kernel.util.FileUtil; 
String fileName = FileUtil.stripExtension(file.getName());

Use FilenameUtils.removeExtension from Apache Commons IO

Example:

You can provide full path name or only the file name.

String myString1 = FilenameUtils.removeExtension("helloworld.exe"); // returns "helloworld"
String myString2 = FilenameUtils.removeExtension("/home/abc/yey.xls"); // returns "yey"

Hope this helps ..


The easiest way is to use a regular expression.

fileNameWithOutExt = "test.xml".replaceFirst("[.][^.]+$", "");

The above expression will remove the last dot followed by one or more characters. Here's a basic unit test.

public void testRegex() {
    assertEquals("test", "test.xml".replaceFirst("[.][^.]+$", ""));
    assertEquals("test.2", "test.2.xml".replaceFirst("[.][^.]+$", ""));
}

If you don't like to import the full apache.commons, I've extracted the same functionality:

public class StringUtils {
    public static String getBaseName(String filename) {
        return removeExtension(getName(filename));
    }

    public static int indexOfLastSeparator(String filename) {
        if(filename == null) {
            return -1;
        } else {
            int lastUnixPos = filename.lastIndexOf(47);
            int lastWindowsPos = filename.lastIndexOf(92);
            return Math.max(lastUnixPos, lastWindowsPos);
        }
    }

    public static String getName(String filename) {
        if(filename == null) {
            return null;
        } else {
            int index = indexOfLastSeparator(filename);
            return filename.substring(index + 1);
        }
    }

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

    public static int indexOfExtension(String filename) {
        if(filename == null) {
            return -1;
        } else {
            int extensionPos = filename.lastIndexOf(46);
            int lastSeparator = indexOfLastSeparator(filename);
            return lastSeparator > extensionPos?-1:extensionPos;
        }
    }
}

You can use java split function to split the filename from the extension, if you are sure there is only one dot in the filename which for extension.

File filename = new File('test.txt'); File.getName().split("[.]");

so the split[0] will return "test" and split[1] will return "txt"


If your project uses Guava (14.0 or newer), you can go with Files.getNameWithoutExtension().

(Essentially the same as FilenameUtils.removeExtension() from Apache Commons IO, as the highest-voted answer suggests. Just wanted to point out Guava does this too. Personally I didn't want to add dependency to Commons—which I feel is a bit of a relic—just because of this.)


Keeping it simple, use Java's String.replaceAll() method as follows:

String fileNameWithExt = "test.xml";
String fileNameWithoutExt
   = fileNameWithExt.replaceAll( "^.*?(([^/\\\\\\.]+))\\.[^\\.]+$", "$1" );

This also works when fileNameWithExt includes the fully qualified path.


Simplest way to get name from relative path or full path is using

import org.apache.commons.io.FilenameUtils; FilenameUtils.getBaseName(definitionFilePath)


You can split it by "." and on index 0 is file name and on 1 is extension, but I would incline for the best solution with FileNameUtils from apache.commons-io like it was mentioned in the first article. It does not have to be removed, but sufficent is:

String fileName = FilenameUtils.getBaseName("test.xml");


While I am a big believer in reusing libraries, the org.apache.commons.io JAR is 174KB, which is noticably large for a mobile app.

If you download the source code and take a look at their FilenameUtils class, you can see there are a lot of extra utilities, and it does cope with Windows and Unix paths, which is all lovely.

However, if you just want a couple of static utility methods for use with Unix style paths (with a "/" separator), you may find the code below useful.

The removeExtension method preserves the rest of the path along with the filename. There is also a similar getExtension.

/**
 * Remove the file extension from a filename, that may include a path.
 * 
 * e.g. /path/to/myfile.jpg -> /path/to/myfile 
 */
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);
    }
}

/**
 * Return the file extension from a filename, including the "."
 * 
 * e.g. /path/to/myfile.jpg -> .jpg
 */
public static String getExtension(String filename) {
    if (filename == null) {
        return null;
    }

    int index = indexOfExtension(filename);

    if (index == -1) {
        return filename;
    } else {
        return filename.substring(index);
    }
}

private static final char EXTENSION_SEPARATOR = '.';
private static final char DIRECTORY_SEPARATOR = '/';

public static int indexOfExtension(String filename) {

    if (filename == null) {
        return -1;
    }

    // Check that no directory separator appears after the 
    // EXTENSION_SEPARATOR
    int extensionPos = filename.lastIndexOf(EXTENSION_SEPARATOR);

    int lastDirSeparator = filename.lastIndexOf(DIRECTORY_SEPARATOR);

    if (lastDirSeparator > extensionPos) {
        LogIt.w(FileSystemUtil.class, "A directory separator appears after the file extension, assuming there is no file extension");
        return -1;
    }

    return extensionPos;
}

The fluent way:

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

For Kotlin it's now simple as:

val fileNameStr = file.nameWithoutExtension

Below is reference from https://android.googlesource.com/platform/tools/tradefederation/+/master/src/com/android/tradefed/util/FileUtil.java

/**
 * Gets the base name, without extension, of given file name.
 * <p/>
 * e.g. getBaseName("file.txt") will return "file"
 *
 * @param fileName
 * @return the base name
 */
public static String getBaseName(String fileName) {
    int index = fileName.lastIndexOf('.');
    if (index == -1) {
        return fileName;
    } else {
        return fileName.substring(0, index);
    }
}

Try the code below. Using core Java basic functions. It takes care of Strings with extension, and without extension (without the '.' character). The case of multiple '.' is also covered.

String str = "filename.xml";
if (!str.contains(".")) 
    System.out.println("File Name=" + str); 
else {
    str = str.substring(0, str.lastIndexOf("."));
    // Because extension is always after the last '.'
    System.out.println("File Name=" + str);
}

You can adapt it to work with null strings.


See the following test program:

public class javatemp {
    static String stripExtension (String str) {
        // Handle null case specially.

        if (str == null) return null;

        // Get position of last '.'.

        int pos = str.lastIndexOf(".");

        // If there wasn't any '.' just return the string as is.

        if (pos == -1) return str;

        // Otherwise return the string, up to the dot.

        return str.substring(0, pos);
    }

    public static void main(String[] args) {
        System.out.println ("test.xml   -> " + stripExtension ("test.xml"));
        System.out.println ("test.2.xml -> " + stripExtension ("test.2.xml"));
        System.out.println ("test       -> " + stripExtension ("test"));
        System.out.println ("test.      -> " + stripExtension ("test."));
    }
}

which outputs:

test.xml   -> test
test.2.xml -> test.2
test       -> test
test.      -> test