Bagaimana cara mendapatkan nama file tanpa ekstensi di Java?

Jawaban:

429

Jika Anda, seperti saya, lebih suka menggunakan beberapa kode pustaka di mana mereka mungkin telah memikirkan semua kasus khusus, seperti apa yang terjadi jika Anda memasukkan nol atau titik di jalur tetapi tidak dalam nama file, Anda dapat menggunakan yang berikut:

import org.apache.commons.io.FilenameUtils;
String fileNameWithOutExt = FilenameUtils.removeExtension(fileNameWithExt);
Ulf Lindback
sumber
61
Anda juga dapat menggunakan FilenameUtils.getBasename untuk langsung dari string path ke nama file-tanpa-ekstensi.
Ian Durkan
2
Yang termudah tentu saja menjalankan maven :-) Jika tidak, lihat: commons.apache.org/io
Ulf Lindback
8
Bagi mereka yang lebih suka jambu biji, bisa juga melakukan ini . (Hari ini saya pribadi tidak merasa senang menambahkan ketergantungan Apache Commons, meskipun secara historis perpustakaan-perpustakaan itu sangat berguna.)
Jonik
3
Sementara Guava dan Commons-IO dapat menawarkan sedikit tambahan, Anda akan terkejut betapa banyak metode kenyamanan sudah termasuk dalam JDK 7 dengan java.nio.file.Filesdan Path- seperti menyelesaikan direktori basis, menyalin satu baris / memindahkan file, hanya mendapatkan nama file dll.
Don Cheadle
3
@Lan Durkan saat ini FilenameUtils.getBaseName dengan modal N
Slow Harry
153

Cara termudah adalah dengan menggunakan ekspresi reguler.

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

Ekspresi di atas akan menghapus titik terakhir diikuti oleh satu atau lebih karakter. Inilah tes unit dasar.

public void testRegex() {
    assertEquals("test", "test.xml".replaceFirst("[.][^.]+$", ""));
    assertEquals("test.2", "test.2.xml".replaceFirst("[.][^.]+$", ""));
}
brianegge
sumber
11
Regex tidak mudah digunakan seperti solusi perpustakaan di atas. Ini berfungsi, tetapi melihat kode (tanpa harus menafsirkan REGEX) tidak jelas apa fungsinya.
Gustavo Litovsky
5
@GustavoLitovsky Android tidak dibundel dengan org.apache.commons. Sejauh yang saya ketahui, ini adalah satu-satunya cara untuk melakukannya di Android.
Liam George Betsworth
1
/ * regex berikut ini juga menghapus jalur * / "/the/path/name.extension".replaceAll(".*[##################" "") ;
daggett
1
Saya akan menambahkan garis miring ke kelas karakter kedua untuk memastikan bahwa Anda tidak tersandung oleh jalur seperti "/foo/bar.x/baz"
chrisinmtown
53

Lihat program pengujian berikut:

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

yang keluaran:

test.xml   -> test
test.2.xml -> test.2
test       -> test
test.      -> test
paxdiablo
sumber
Apa perpanjangan foo.tar.gz? Saya bisa melihat mengapa .tar.gzAnda menginginkannya.
tchrist
5
@tchrist, foo.tar.gzadalah versi gzip foo.tarjadi Anda juga bisa berargumen bahwa gzitu adalah ekstensi. Itu semua bermuara pada bagaimana Anda mendefinisikan ekstensi.
paxdiablo
2
apa yang harus dilakukan dengan file seperti .gitignore?
michael nesterenko
seperti yang Anda ketahui nama kelas di java tidak boleh dimulai dengan huruf kecil!
AnujKu
7
Jika itu aturan, bahasa akan memberlakukannya. Karena tidak, itu adalah pedoman namun sangat disarankan. Bagaimanapun, itu sama sekali tidak relevan dengan pertanyaan dan jawaban.
paxdiablo
47

Ini adalah urutan daftar konsolidasi berdasarkan preferensi saya.

Menggunakan apache commons

import org.apache.commons.io.FilenameUtils;

String fileNameWithoutExt = FilenameUtils.getBaseName(fileName);

                           OR

String fileNameWithOutExt = FilenameUtils.removeExtension(fileName);

Menggunakan Google Guava (Jika Anda sudah menggunakannya)

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

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

API Liferay

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

Jika proyek Anda menggunakan Guava (14.0 atau lebih baru), Anda dapat menggunakannya Files.getNameWithoutExtension().

(Pada dasarnya sama dengan FilenameUtils.removeExtension() dari Apache Commons IO, seperti yang disarankan oleh pilihan tertinggi . Hanya ingin menunjukkan Guava melakukan hal ini juga. Secara pribadi saya tidak ingin menambahkan ketergantungan pada Commons — yang saya rasa agak seperti peninggalan— hanya karena ini.)

Jonik
sumber
2
sebenarnya itu lebih sepertiFilenameUtils.getBaseName()
Angelo.Hannes
sebenarnya jambu biji adalah lib yang tidak stabil sehingga saya hanya menghindari menggunakannya di mana pun saya bisa. lebih suka peninggalan yang stabil daripada percobaan oleh googel
Slava
8

Di bawah ini adalah referensi dari 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
sumber
1
Info bagus, tetapi pengguna, waspadai kasus seperti ".htaccess", tempat metode ini akan mengembalikan "".
Markus Schulte
6

Jika Anda tidak suka mengimpor apache.commons lengkap, saya telah mengekstrak fungsi yang sama:

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
sumber
4

Sementara saya sangat percaya dalam menggunakan kembali perpustakaan, JAR org.apache.commons.io adalah 174KB, yang sangat besar untuk aplikasi seluler.

Jika Anda mengunduh kode sumber dan melihat kelas FilenameUtils mereka, Anda dapat melihat ada banyak utilitas tambahan, dan itu mengatasi jalur Windows dan Unix, yang semuanya menyenangkan.

Namun, jika Anda hanya ingin beberapa metode utilitas statis untuk digunakan dengan jalur gaya Unix (dengan pemisah "/"), Anda mungkin menemukan kode di bawah ini bermanfaat.

The removeExtensionMetode mempertahankan sisa jalan bersama dengan nama file. Ada juga yang mirip 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
sumber
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
sumber
1

Cara termudah untuk mendapatkan nama dari jalur relatif atau jalur lengkap adalah menggunakan

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

Chetan Nehete
sumber
0

Anda dapat membaginya dengan "." dan pada indeks 0 adalah nama file dan pada 1 adalah ekstensi, tapi saya akan cenderung untuk solusi terbaik dengan FileNameUtils dari apache.commons-io seperti yang disebutkan dalam artikel pertama. Itu tidak harus dihapus, tetapi cukup adalah:

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

Peter S.
sumber
0

Gunakan FilenameUtils.removeExtensiondari Apache Commons IO

Contoh:

Anda dapat memberikan nama path lengkap atau hanya nama file .

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

Semoga ini membantu ..

Dulith De Costa
sumber
Itu sudah ada dalam jawaban yang diterima, apa gunanya posting ini?
Tom
0

Cara lancar:

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

Tetap sederhana, gunakan metode String.replaceAll () Java sebagai berikut:

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

Ini juga berfungsi ketika fileNameWithExt menyertakan jalur yang sepenuhnya memenuhi syarat.

gwc
sumber
0

Anda dapat menggunakan fungsi java split untuk memisahkan nama file dari ekstensi, jika Anda yakin hanya ada satu titik di nama file yang untuk ekstensi.

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

sehingga split[0]akan mengembalikan "test" dan split [1] akan mengembalikan "txt"

Ahmed Denmark
sumber
-3

Coba kode di bawah ini. Menggunakan fungsi dasar inti Java. Ini menangani Strings dengan ekstensi, dan tanpa ekstensi (tanpa '.'karakter). Kasus multiple '.'juga dibahas.

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

Anda dapat menyesuaikannya agar berfungsi dengan nullstring.

Sksoni
sumber
1
Ini praktik yang sangat buruk untuk mengimplementasikan fungsi semacam ini sendiri. Pada pandangan pertama tugas tersebut tampaknya sangat jelas , tetapi dalam praktiknya Anda akan menghadapi banyak situasi luar biasa (seperti tidak ada .dalam nama file, atau file adalah cadangan dan memiliki nama seperti document.docx.backup, dll). Jauh lebih dapat diandalkan untuk menggunakan perpustakaan eksternal yang berhubungan dengan semua situasi luar biasa ini untuk Anda.
ivstas
1
Di sisi lain, menambah banyak pustaka ke proyek Anda akan membuatnya lebih besar. Jadi hal-hal sederhana seperti ini bisa dilakukan sendiri.
Nicolas Tyler
1
Tidak mungkin Anda harus melakukan ini sendiri. Ini sulit: file tanpa ekstensi tetapi. di path, ftp paths, windows dan unix slash, tautan simbolik dll ... Anda pasti akan gagal dan dengan mencoba mendapatkan sedikit memori Anda akan membuat banyak ketidakstabilan. Paling tidak salin sumber kode yang ditetapkan jika lisensi mengizinkannya.
Jonathan Nappee
Kode ini terlihat seperti kode dari Amit Mishra, kecuali untuk mengintimidasi 'if (! Str.contains ("."))'
Broken_Window
akan gagal dalam kasus berikut "/someFolder/some.other.folder/someFileWithoutExtention". Hal pertama yang muncul dalam pikiran setelah 2 detik .. saya yakin saya bisa menghasilkan banyak contoh lainnya.
Newtopian