Jak uzyskać nazwę pliku bez rozszerzenia w Javie?

Odpowiedzi:

429

Jeśli, podobnie jak ja, wolisz użyć kodu biblioteki, w którym prawdopodobnie pomyśleli o wszystkich specjalnych przypadkach, takich jak to, co się stanie, jeśli wpiszesz null lub kropki na ścieżce, ale nie w nazwie pliku, możesz użyć następującego:

import org.apache.commons.io.FilenameUtils;
String fileNameWithOutExt = FilenameUtils.removeExtension(fileNameWithExt);
Ulf Lindback
źródło
61
możesz także użyć FilenameUtils.getBasename, aby przejść bezpośrednio od ciągu ścieżki do nazwy pliku bez rozszerzenia.
Ian Durkan
2
Najłatwiej jest oczywiście uruchomić maven :-) W przeciwnym razie zobacz: commons.apache.org/io
Ulf Lindback
8
Dla tych, którzy wolą Guava, może to zrobić . (Te dni Osobiście nie czuję się bardzo dobrze o dodanie Apache Commons zależności, choć historycznie te biblioteki są bardzo użyteczne.)
Jonik
3
Chociaż Guava i Commons-IO mogą zaoferować trochę więcej, zdziwiłbyś się, ile metod wygody jest już zawartych w JDK 7 przy pomocy java.nio.file.Filesi Path- takich jak rozwiązywanie katalogów podstawowych, kopiowanie / przenoszenie plików w jednym wierszu, uzyskiwanie tylko nazwy pliku itp.
Don Cheadle
3
@Lan Durkan obecnie Nazwa plikuUtils.getBaseName z dużą literą N
Powolny Harry
153

Najprostszym sposobem jest użycie wyrażenia regularnego.

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

Powyższe wyrażenie usunie ostatnią kropkę, po której następuje jeden lub więcej znaków. Oto podstawowy test jednostkowy.

public void testRegex() {
    assertEquals("test", "test.xml".replaceFirst("[.][^.]+$", ""));
    assertEquals("test.2", "test.2.xml".replaceFirst("[.][^.]+$", ""));
}
Brianegge
źródło
11
Regex nie jest tak łatwy w użyciu jak powyższe rozwiązanie biblioteczne. Działa, ale patrzenie na kod (bez konieczności interpretowania REGEXU) nie jest oczywiste, co robi.
Gustavo Litovsky
5
@GustavoLitovsky Android nie jest dostarczany w pakiecie org.apache.commons. O ile mi wiadomo, jest to jedyny sposób, aby to zrobić w Androidzie.
Liam George Betsworth,
1
/ * następujący wyrażenie regularne usuwa również ścieżkę * / "/the/path/name.extension".replaceAll(".*[\\\\/]|\\.[^\\.]*$", "" ;
daggett
1
Dodałbym ukośniki do drugiej klasy postaci, aby upewnić się, że nie potknie Cię ścieżka typu „/foo/bar.x/baz”
chrisinmtown
53

Zobacz następujący program testowy:

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

które wyjścia:

test.xml   -> test
test.2.xml -> test.2
test       -> test
test.      -> test
paxdiablo
źródło
Jakie jest rozszerzenie foo.tar.gz? Rozumiem, dlaczego .tar.gzmiałbyś być tym, czego chcesz.
tchrist 30.08.11
5
@tchrist, foo.tar.gzjest wersją spakowaną gzipem, foo.tarwięc możesz również argumentować, że to gzbyło rozszerzenie. Wszystko sprowadza się do sposobu definiowania rozszerzenia.
paxdiablo
2
co zrobić z takimi plikami .gitignore?
Michael Nesterenko
jak wiesz, nazwa klasy w java nigdy nie powinna zaczynać się od małej litery!
AnujKu
7
Gdyby to była reguła, język by ją egzekwował. Ponieważ tak nie jest, jest to wytyczna, jakkolwiek zdecydowanie sugerowana. W każdym razie nie ma to znaczenia dla pytania i odpowiedzi.
paxdiablo
47

Oto skonsolidowana kolejność list według moich preferencji.

Używanie wspólnego apache

import org.apache.commons.io.FilenameUtils;

String fileNameWithoutExt = FilenameUtils.getBaseName(fileName);

                           OR

String fileNameWithOutExt = FilenameUtils.removeExtension(fileName);

Korzystanie z Google Guava (jeśli już go używasz)

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

Lub używając 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);
}

2)

if (fileName.indexOf(".") > 0) {
   return fileName.substring(0, fileName.lastIndexOf("."));
} else {
   return fileName;
}

3)

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());
Om.
źródło
42

Jeśli twój projekt używa Guava (14.0 lub nowszy), możesz iść z Files.getNameWithoutExtension().

(Zasadniczo taki sam, jak w FilenameUtils.removeExtension()Apache Commons IO, jak sugeruje najwyżej głosowana odpowiedź . Chciałem tylko zaznaczyć, że Guava też to robi. Osobiście nie chciałem dodawać zależności do Commons - co wydaje mi się trochę reliktem - właśnie z tego powodu).

Jonik
źródło
2
w rzeczywistości jest bardziej jakFilenameUtils.getBaseName()
Angelo.Hannes
w rzeczywistości guawa jest tak niestabilną biblioteką, że po prostu unikam jej używania, gdzie tylko mogę. wolą stabilną reliktę niż eksperymenty googela
Slava
8

Poniżej znajduje się odniesienie od 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);
    }
}
David Cheung
źródło
1
Ładne informacje, ale użytkownicy powinni pamiętać o przypadkach takich jak „.htaccess”, w których ta metoda zwróci „”.
Markus Schulte
6

Jeśli nie chcesz importować pełnego apache.commons, wyodrębniłem tę samą funkcjonalność:

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;
        }
    }
}
Hamzeh Soboh
źródło
4

Chociaż jestem zwolennikiem ponownego wykorzystywania bibliotek, JAR org.apache.commons.io ma wielkość 174 KB, co jest szczególnie duże jak na aplikację mobilną.

Jeśli pobierzesz kod źródłowy i spojrzysz na jego klasę FilenameUtils, zobaczysz, że istnieje wiele dodatkowych narzędzi i poradzi sobie ze ścieżkami Windows i Unix, co jest cudowne.

Jeśli jednak potrzebujesz kilku statycznych metod narzędziowych do użycia ze ścieżkami w stylu uniksowym (z separatorem „/”), poniższy kod może ci się przydać.

removeExtensionSposób zachowuje resztę toru wraz z pliku. Jest też podobny 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;
}
Dan J.
źródło
1
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("."));
    }
Gil SH
źródło
1

Najprostszy sposób na uzyskanie nazwy ze ścieżki względnej lub ścieżki pełnej

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

Chetan Nehete
źródło
0

Możesz podzielić to przez „.” a na indeksie 0 jest nazwa pliku, a na 1 jest rozszerzenie, ale chciałbym uzyskać najlepsze rozwiązanie z FileNameUtils z apache.commons-io, jak wspomniano w pierwszym artykule. Nie trzeba go usuwać, ale wystarczające jest:

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

Peter S.
źródło
0

Użyj FilenameUtils.removeExtensionz Apache Commons IO

Przykład:

Możesz podać pełną nazwę ścieżki lub tylko nazwę pliku .

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

Mam nadzieję że to pomoże ..

Dulith De Costa
źródło
To już jest w zaakceptowanej odpowiedzi, jaki jest sens tego postu?
Tom
0

Płynny sposób:

public static String fileNameWithOutExt (String fileName) {
    return Optional.of(fileName.lastIndexOf(".")).filter(i-> i >= 0)
            .map(i-> fileName.substring(0, i)).orElse(fileName);
}
Nolle
źródło
0

Upraszczając, użyj metody String.replaceAll () w języku Java w następujący sposób:

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

Działa to również wtedy, gdy fileNameWithExt zawiera pełną ścieżkę.

gwc
źródło
0

Możesz użyć funkcji java split, aby podzielić nazwę pliku z rozszerzenia, jeśli masz pewność, że w nazwie pliku jest tylko jedna kropka, która jest rozszerzeniem.

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

więc split[0]zwróci „test”, a split [1] zwróci „txt”

Duński Ahmed
źródło
-3

Wypróbuj poniższy kod. Korzystanie z podstawowych funkcji Java. Dba o Strings z rozszerzeniem i bez rozszerzenia (bez '.'znaku). Przypadek wielokrotności '.'jest również objęty.

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

Możesz dostosować go do pracy z nullłańcuchami.

Sksoni
źródło
1
Bardzo złą praktyką jest samodzielne wdrażanie tego rodzaju funkcji. Na pierwszy rzut oka zadanie wydaje się niezwykle oczywiste , ale w praktyce napotkasz wiele wyjątkowych sytuacji (np. Nie ma .nazwy pliku lub plik jest kopią zapasową i ma nazwę podobną document.docx.backupitp.). O wiele bardziej niezawodne jest korzystanie z zewnętrznej biblioteki, która zajmuje się wszystkimi tymi wyjątkowymi sytuacjami.
ivstas
1
Z drugiej strony dodanie do wielu bibliotek projektu zwiększy go. Tak proste rzeczy takie jak to można zrobić samemu.
Nicolas Tyler,
1
Nie ma mowy, żebyś sam to zrobił. To trudne: pliki bez rozszerzenia, ale. w ścieżce, ścieżkach ftp, ukośnikach Windows i Unix, symbolicznych linkach itp. Z pewnością zawiedziesz, a próbując zyskać trochę pamięci, reklamujesz dużo niestabilności. Przy minimalnej kopii źródła ustalonego kodu, jeśli pozwalają na to licencje.
Jonathan Nappee
Ten kod wygląda jak ten z Amit Mishra, z wyjątkiem tego zastraszającego „jeśli (! Str. Zawiera („. ”))”
Broken_Window
zakończy się niepowodzeniem w następującym przypadku „/someFolder/some.other.folder/someFileWithoutExtention”. Pierwsza rzecz, która przyszła mi do głowy po 2 sekundach ... jestem pewien, że mógłbym wymyślić mnóstwo innych przykładów.
Newtopian