วิธีรับชื่อไฟล์โดยไม่มีนามสกุลใน Java


266

ทุกคนสามารถบอกวิธีรับชื่อไฟล์โดยไม่มีนามสกุลได้หรือไม่? ตัวอย่าง:

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

คำตอบ:


429

หากคุณชอบฉันจะใช้รหัสห้องสมุดที่พวกเขาอาจนึกถึงกรณีพิเศษทั้งหมดเช่นเกิดอะไรขึ้นถ้าคุณผ่านเป็นโมฆะหรือจุดในเส้นทาง แต่ไม่ใช่ในชื่อไฟล์คุณสามารถใช้สิ่งต่อไปนี้:

import org.apache.commons.io.FilenameUtils;
String fileNameWithOutExt = FilenameUtils.removeExtension(fileNameWithExt);

61
คุณยังสามารถใช้ FilenameUtils.getBasename เพื่อไปจากสตริงพา ธ ไปยัง filename-without-extension
Ian Durkan

2
ที่ง่ายที่สุดคือการรัน maven แน่นอน :-) มิฉะนั้นดู: commons.apache.org/io
Ulf Lindback

8
สำหรับผู้ที่ชื่นชอบ Guava ก็สามารถทำได้เช่นกัน (วันนี้ฉันไม่รู้สึกดีกับการเพิ่ม Apache Commons แต่โดยส่วนตัวแล้วในอดีตห้องสมุดเหล่านั้นมีประโยชน์มาก)
Jonik

3
ในขณะที่ Guava และ Commons-IO อาจมีข้อเสนอเพิ่มเติมเล็กน้อยคุณจะประหลาดใจว่ามีวิธีการอำนวยความสะดวกหลายอย่างที่รวมอยู่ใน JDK 7ด้วยjava.nio.file.FilesและPath- เช่นการแก้ไขไดเรกทอรีพื้นฐานไฟล์คัดลอก / ย้ายหนึ่งบรรทัดรับชื่อไฟล์เท่านั้น ฯลฯ
Don Cheadle

3
@Lan Durkan ในขณะนี้ชื่อไฟล์ Utils.getBaseName ด้วยทุนจดทะเบียน N
Slow Harry

153

วิธีที่ง่ายที่สุดคือการใช้นิพจน์ทั่วไป

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

นิพจน์ด้านบนจะลบจุดสุดท้ายตามด้วยอักขระหนึ่งตัวขึ้นไป นี่คือการทดสอบหน่วยพื้นฐาน

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

11
Regex นั้นไม่ได้ใช้งานง่ายเหมือนโซลูชันไลบรารีด้านบน มันใช้งานได้ แต่การดูรหัส (โดยไม่ต้องตีความ REGEX) ไม่ชัดเจนว่ามันทำอะไร
Gustavo Litovsky

5
@GustavoLitovsky Android org.apache.commonsไม่มาพร้อมกับ เท่าที่ฉันทราบนี่เป็นวิธีเดียวที่จะทำได้ใน Android
เลียมจอร์จเบตส์เวิร์ ธ

1
/ * regex ต่อไปนี้จะลบพา ธ * / "/ the/path/name.extension".replaceAll(".* ออสเตรีย" สำหรับ "ที่อยู่", "") ;
daggett

1
ฉันจะเพิ่มเครื่องหมายสแลชในคลาสอักขระที่สองเพื่อให้แน่ใจว่าคุณจะไม่สะดุดโดยเส้นทางเช่น "/foo/bar.x/baz"
chrisinmtown

53

ดูโปรแกรมทดสอบต่อไปนี้:

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

ผลลัพธ์ใด:

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

ส่วนขยายของfoo.tar.gzอะไร ฉันสามารถดูว่าทำไม.tar.gzจะเป็นสิ่งที่คุณต้องการ
tchrist

5
@tchrist foo.tar.gzเป็นรุ่น gzipped foo.tarดังนั้นคุณสามารถยืนยันว่าgzเป็นส่วนขยาย ทุกอย่างลงมาถึงวิธีที่คุณกำหนดส่วนขยาย
paxdiablo

2
จะทำอย่างไรกับไฟล์เช่น.gitignore?
michael nesterenko

อย่างที่คุณทราบชื่อคลาสในจาวาไม่ควรเริ่มด้วยตัวอักษรเล็ก!
AnujKu

7
หากนั่นเป็นกฎภาษาจะบังคับใช้ เนื่องจากไม่เป็นเช่นนั้นมันเป็นแนวทาง แต่แนะนำอย่างยิ่ง ไม่ว่าในกรณีใดก็ตามนั่นไม่เกี่ยวข้องกับคำถามและคำตอบทั้งหมด
paxdiablo

47

นี่คือลำดับรายการรวมตามความต้องการของฉัน

ใช้ apache ทั่วไป

import org.apache.commons.io.FilenameUtils;

String fileNameWithoutExt = FilenameUtils.getBaseName(fileName);

                           OR

String fileNameWithOutExt = FilenameUtils.removeExtension(fileName);

ใช้ Google Guava (ถ้าคุณใช้อยู่แล้ว)

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

หรือใช้ 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());

42

หากโครงการของคุณใช้Guava (14.0 หรือใหม่กว่า) คุณสามารถไปกับFiles.getNameWithoutExtension()คุณสามารถไปกับ

(โดยพื้นฐานแล้วก็เหมือนกับFilenameUtils.removeExtension()Apache Commons IO ซึ่งเป็นคำตอบที่ได้รับการโหวตมากที่สุดอยากจะชี้ให้เห็นว่า Guava ทำเช่นนี้โดยส่วนตัวแล้วฉันไม่ต้องการเพิ่มการพึ่งพา Commons ซึ่งฉันรู้สึกว่าเป็นของที่ระลึก - เพียงเพราะสิ่งนี้)


2
ที่จริงแล้วมันเป็นเช่นนั้นมากขึ้นFilenameUtils.getBaseName()
Angelo.Hannes

ฝรั่งจริงๆแล้วมันเป็น lib ที่ไม่แน่นอนที่ฉันหลีกเลี่ยงการใช้มันทุกที่ที่ทำได้ ชอบของที่ระลึกมั่นคงมากกว่าการทดลองโดย googel
Slava

8

ด้านล่างนี้เป็นการอ้างอิงจาก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);
    }
}

1
ข้อมูลที่ดี แต่ผู้ใช้พึงระวังกรณีเช่น ".htaccess" ซึ่งวิธีนี้จะส่งคืน ""
Markus Schulte

6

หากคุณไม่ต้องการที่จะนำเข้า apache.com เต็มรูปแบบฉันได้แยกการทำงานแบบเดียวกัน:

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

4

ในขณะที่ฉันเป็นผู้เชื่อที่ยิ่งใหญ่ในการนำห้องสมุดมาใช้ซ้ำorg.apache.commons.io JARคือ 174KB ซึ่งมีขนาดใหญ่มากสำหรับแอพมือถือ

หากคุณดาวน์โหลดซอร์สโค้ดและดูที่ FilenameUtils class คุณจะเห็นว่ามียูทิลิตีพิเศษมากมายและมันรับมือกับเส้นทาง Windows และ Unix ซึ่งน่ารักมาก

อย่างไรก็ตามหากคุณต้องการวิธีการยูทิลิตี้แบบคงที่สองสามอย่างสำหรับใช้กับ Unix style path (ที่มีตัวคั่น "/") คุณอาจพบโค้ดด้านล่างนี้มีประโยชน์

removeExtensionวิธีการเก็บรักษาส่วนที่เหลือของเส้นทางพร้อมกับชื่อไฟล์ 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;
}

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

1

วิธีที่ง่ายที่สุดในการรับชื่อจากพา ธ สัมพัทธ์หรือพา ธ เต็มใช้

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


0

คุณสามารถแยกมันด้วย "." และในดัชนี 0 คือชื่อไฟล์และในวันที่ 1 เป็นส่วนขยาย แต่ฉันอยากจะหาทางออกที่ดีที่สุดกับ FileNameUtils จาก apache.commons-io เหมือนที่กล่าวไว้ในบทความแรก ไม่จำเป็นต้องลบออก แต่พอเพียงคือ:

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


0

ใช้FilenameUtils.removeExtensionจากApache Commons IO

ตัวอย่าง:

คุณสามารถระบุชื่อเส้นทางแบบเต็มหรือชื่อไฟล์อย่างเดียว

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

หวังว่านี่จะช่วย ..


มีอยู่ในคำตอบที่ยอมรับแล้วจุดประสงค์ของโพสต์นี้คืออะไร
ทอม

0

วิธีที่คล่องแคล่ว:

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

0

ทำให้เป็นเรื่องง่ายโดยใช้เมธอด String.replaceAll () ของ Java ดังต่อไปนี้:

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

สิ่งนี้ยังทำงานเมื่อ fileNameWithExt รวมถึงพา ธ แบบเต็ม


0

คุณสามารถใช้ฟังก์ชั่นการแยกจาวาเพื่อแยกชื่อไฟล์จากส่วนขยายหากคุณแน่ใจว่ามีจุดเพียงจุดเดียวในชื่อไฟล์ที่ใช้สำหรับการขยาย

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

ดังนั้นความsplit[0]ประสงค์จะกลับมา "ทดสอบ" และแยก [1] จะกลับมา "txt"


-3

ลองรหัสด้านล่าง การใช้ฟังก์ชั่นพื้นฐานของ Java หลัก มันจะดูแลStrings ที่มีนามสกุลและไม่มีนามสกุล (ไม่มี'.'อักขระ) กรณีของหลาย'.'จะครอบคลุมด้วย

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

คุณสามารถปรับมันเพื่อทำงานกับnullสตริง


1
เป็นการปฏิบัติที่ไม่ดีพอที่จะใช้งานฟังก์ชั่นนี้ด้วยตัวคุณเอง ในครั้งแรกที่ดูเหมือนว่างานจะชัดเจนมากแต่ในทางปฏิบัติคุณจะต้องเผชิญกับสถานการณ์พิเศษมากมาย (เช่นไม่มี.ชื่อไฟล์หรือไฟล์เป็นการสำรองข้อมูลและมีชื่อเหมือนdocument.docx.backupฯลฯ ) มันมีความน่าเชื่อถือมากกว่าการใช้ไลบรารี่ภายนอกที่เกี่ยวข้องกับสถานการณ์พิเศษทั้งหมดนี้สำหรับคุณ
ivstas

1
ในทางกลับกันการเพิ่มไปยังไลบรารีจำนวนมากในโครงการของคุณจะทำให้ใหญ่ขึ้น สิ่งง่าย ๆ แบบนี้สามารถทำได้ด้วยตัวเอง
Nicolas Tyler

1
ไม่มีทางที่คุณควรทำสิ่งนี้ด้วยตัวเอง นี่เป็นเรื่องยาก: ไฟล์ที่ไม่มีนามสกุล แต่ ในพา ธ , เส้นทาง ftp, windows และ unix slashes, ลิงก์สัญลักษณ์ ฯลฯ ... คุณจะล้มเหลวอย่างแน่นอนและพยายามเพิ่มหน่วยความจำสักเล็กน้อยคุณจะโฆษณาอย่างไม่มั่นคง อย่างน้อยที่สุดก็อปปี้แหล่งที่มาของรหัสที่กำหนดถ้าใบอนุญาตอนุญาต
Jonathan Nappee

รหัสนี้ดูเหมือนว่ามาจาก Amit Mishra ยกเว้นการข่มขู่ 'if (! str.containers ("."))'
Broken_Window

จะล้มเหลวในกรณีต่อไปนี้ "/someFolder/some.other.folder/someFileWithoutExtention" สิ่งแรกที่ผุดขึ้นในใจหลังจาก 2 วินาที .. ฉันแน่ใจว่าฉันสามารถหาตัวอย่างอื่นได้อีกมากมาย
Newtopian
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.