ฉันจะรับนามสกุลไฟล์ของไฟล์ใน Java ได้อย่างไร?


484

เพื่อความชัดเจนฉันไม่ได้มองหาประเภท MIME

สมมติว่าฉันมีอินพุตต่อไปนี้: /path/to/file/foo.txt

ฉันต้องการแยกวิธีการป้อนข้อมูลนี้โดยเฉพาะ.txtสำหรับส่วนขยาย มีวิธีใดบ้างที่จะทำสิ่งนี้ใน Java? ฉันต้องการหลีกเลี่ยงการเขียนโปรแกรมแยกวิเคราะห์ของฉันเอง


12
คุณไม่มีทางรู้ว่าเมื่อใดจะมีแพลตฟอร์มใหม่เกิดขึ้นซึ่งจะกำหนดส่วนขยายว่าถูกคั่นด้วยเครื่องหมายจุลภาค ตอนนี้คุณต้องเขียนโค้ดที่ขึ้นกับแพลตฟอร์ม เฟรมเวิร์ก Java ควรมีการคิดล่วงหน้ามากขึ้นและมี API สำหรับรับส่วนขยายโดยที่พวกเขาเขียนโค้ดที่ขึ้นกับแพลตฟอร์มและคุณในฐานะผู้ใช้ API เพียงพูดว่ารับส่วนขยาย
ArtOfWarfare

@ArtOfWarfare: OMG ลองสร้าง 100MB JRE กับการเรียนหลายพันคน แต่โปรดให้แน่ใจว่าจะไม่ใช้วิธีการใด ๆ ซึ่งผลตอบแทน"txt"จากเพราะบางที่ไหนสักแห่งแพลตฟอร์มอาจต้องการที่จะใช้"filename.txt" "filename,txt"
Eric Duminil

@EricDuminil "อย่าใช้วิธีใด ๆ ที่คืนค่า" txt "จาก" filename.txt "" ??? ลองpath.substring(path.lastIndexOf("."));..... และใช่ .. พวกเขาแน่ใจว่าจะไม่ทำสำเนาบางอย่างเพื่ออะไร ...
VelocityPulse

@VelocityPulse นั่นคือว่าสิ่งที่รบกวนจิตใจผม เนื่องจากไม่มีวิธีมาตรฐานในการรับนามสกุลไฟล์คุณจะได้รับคำตอบที่ผิดครึ่งและการใช้งานที่แตกต่างกันเล็กน้อย รหัสของคุณใช้ 2 วิธี (ฉันอยากจะมีวิธีเดียวชัดเจนวิธีหนึ่ง) มันกลับ".txt"มาจาก"filename.txt"ซึ่งอาจไม่ได้ผลลัพธ์ที่ต้องการและที่แย่ที่สุดคือล้มเหลวStringIndexOutOfBoundsExceptionแทนที่จะส่งคืนสตริงว่างหากไม่มีส่วนขยาย
Eric Duminil

คำตอบ:


649

ในกรณีนี้ใช้FilenameUtils.getExtensionจากApache Commons IO

นี่คือตัวอย่างของวิธีการใช้งาน (คุณสามารถระบุพา ธ เต็มหรือชื่อไฟล์):

String ext1 = FilenameUtils.getExtension("/path/to/file/foo.txt"); // returns "txt"
String ext2 = FilenameUtils.getExtension("bar.exe"); // returns "exe"

Maven พึ่งพา:

<dependency>
  <groupId>commons-io</groupId>
  <artifactId>commons-io</artifactId>
  <version>2.6</version>
</dependency>

Gradle Groovy DSL

implementation 'commons-io:commons-io:2.6'

Gradle Kotlin DSL

implementation("commons-io:commons-io:2.6")

คนอื่น ๆhttps://search.maven.org/artifact/commons-io/commons-io/2.6/jar


70
ควรสังเกตว่าจะส่งคืนเฉพาะ "gz" สำหรับไฟล์ชื่อ archive.tar.gz
Zitrax

106
@Zitrax นั่นเป็นเพราะ "gz" เป็นนามสกุลไฟล์
BrainSlugs83

6
@ BrainSlugs83 ดังนั้น "tar" หมายถึงอะไร?
TuGordoBello

31
@zhelon .gzหมายถึงไฟล์ซิป gnu และ. tarหมายถึง (t) ape (ar) chive ดังนั้น. tar.gz เป็นไฟล์ tar ภายในไฟล์ gnu zipped ซึ่งมีนามสกุล. gz
cirovladimir

5
ไม่มีเหตุผลที่จะนำไลบรารีอื่นมาใช้สำหรับงานง่าย ๆ นี้
masterwok

311

คุณต้องการ "parser" จริงๆหรือไม่

String extension = "";

int i = fileName.lastIndexOf('.');
if (i > 0) {
    extension = fileName.substring(i+1);
}

สมมติว่าคุณกำลังติดต่อกับง่าย Windows archive.tar.gzเช่นชื่อไฟล์ไม่ได้สิ่งที่ต้องการ

Btw สำหรับกรณีที่ไดเรกทอรีอาจมี '.' แต่ชื่อไฟล์เอง (เช่น/path/to.a/file) คุณสามารถทำได้

String extension = "";

int i = fileName.lastIndexOf('.');
int p = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));

if (i > p) {
    extension = fileName.substring(i+1);
}

4
ขอบคุณ! แน่นอนว่าคุณอาจต้องใช้ parser / object หากคุณต้องการทำกิจวัตรมากกว่านามสกุล ... บอกว่าถ้าคุณต้องการแค่พา ธ ไดเรกทอรีหลักชื่อไฟล์ (ลบนามสกุล) ฯลฯ ฉัน m มาจาก C # และ. Net ที่เรามีสิ่งนี้: msdn.microsoft.com/en-us/library/…
longda

10
อย่างที่คุณพูดมีหลายสิ่งที่ต้องคิดนอกเหนือจากการใช้ความไร้เดียงสา lastIndexOf (".") ฉันเดาว่า Apache Commons มีวิธีการนี้ซึ่งจะพิจารณาปัญหาที่อาจเกิดขึ้นได้เล็กน้อยทั้งหมด
MatrixFrog

12
ผมคิดว่าi > 0ควรจะเปลี่ยนหรือi >= 0 นี้จะดูแลเช่นชื่อไฟล์i != -1 .htaccess
Pijusn

8
ไม่ว่าโค้ดขนาดสั้นแค่ไหนก็คือ ... คุณยังคงต้องอัปเดต / บำรุงรักษา / ทดสอบ / ทำให้มันพร้อมใช้งานในฐานะผู้พึ่งพาที่สะดวก ... ง่ายกว่ามากถ้ามี lib ที่ทำทั้งหมดอยู่แล้ว
Don Cheadle

2
Gotcha เพิ่มเติมคือถ้าไฟล์จบด้วยจุด ดีกว่าใน lib if (i> p && i <(fileName.length () - 1)) {extension = fileName.substring (i + 1);
tgkprog

97
private String getFileExtension(File file) {
    String name = file.getName();
    int lastIndexOf = name.lastIndexOf(".");
    if (lastIndexOf == -1) {
        return ""; // empty extension
    }
    return name.substring(lastIndexOf);
}

13
ควรสังเกตว่าสิ่งนี้คืนค่า '.' ด้วยเช่นกันดังนั้นนามสกุลไฟล์ของคุณจะเป็น '.txt' ซึ่งตรงข้ามกับ 'txt' ในคำตอบอื่น ๆ
NickEntin

2
Better Answer และ @NickEntin ความคิดเห็นที่ดีขึ้น ในการลบจุด "" " จากส่วนขยายของไฟล์สามารถเขียนเป็น int lastIndexOf = name.lastIndexOf (".") + 1;
Hanzallah Afgan

11
วิธีการนั้นอาจใช้ไม่ได้ในบางกรณีเช่น /usr/bin/foo.bar/httpconf
Iman Akbari

8
@ lukasz1985 1. แพ็คเกจลินุกซ์หลายร้อยรายการสร้างไดเรกทอรีที่มีชื่อเช่น "init.d" นอกจากนี้ยังไม่ปลอดภัยที่จะใช้เส้นทางที่ไม่มีไดเรกทอรีที่มีจุดเพราะมันไม่ผิดกฎหมาย 2. ฉันถูกเข้ารหัสสำหรับ Android ดังนั้นฉันจึงใช้ SDK บางตัว วิธีฉันจำไม่ได้ แต่ฉันเดาstackoverflow.com/a/3571239/2546146ไม่มีข้อบกพร่องนี้
Iman Akbari

6
@Iman Akbari: getName () จะส่งคืนชื่อไฟล์เองเท่านั้นซึ่งจะเป็น "httpconf" ในตัวอย่างของคุณ
ประธานาธิบดี Dreamspace

85

หากคุณใช้ห้องสมุดGuavaคุณสามารถFilesใช้คลาสยูทิลิตี้ มันมีวิธีการเฉพาะ, getFileExtension(). ตัวอย่างเช่น

String path = "c:/path/to/file/foo.txt";
String ext = Files.getFileExtension(path);
System.out.println(ext); //prints txt

นอกจากนี้คุณยังอาจได้รับชื่อไฟล์ด้วยฟังก์ชั่นที่คล้ายกันgetNameWithoutExtension () :

String filename = Files.getNameWithoutExtension(path);
System.out.println(filename); //prints foo

4
จริงๆ? มันเป็นห้องสมุดที่ยอดเยี่ยมเต็มไปด้วยสาธารณูปโภค ส่วนใหญ่ของพวกเขาจะเป็นส่วนหนึ่งของ Java8 เหมือนฝรั่งที่ดีฟังก์ชั่น
JeanValjean

ไม่ใช่ทุกคนที่จะสามารถตัดสินใจได้ว่าจะใช้ห้องสมุดประเภทใด อย่างน้อยเราก็มี Apache Commons แม้ว่าจะเป็นรุ่นเก่า
Lluis Martinez

1
ถ้าคุณเห็นซอร์สโค้ดของgetFileExtensionจริงมันก็int dotIndex = fileName.lastIndexOf('.'); return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1)ไม่ใช่เรื่องใหญ่อะไร นอกจากนี้โปรดทราบว่าFilesทำเครื่องหมายว่า "ไม่เสถียร" ด้วยเหตุผลบางประการ
อัล Mothafar

@ Al-Mothafar มีหลายคลาสที่ทำเครื่องหมายว่าไม่เสถียร (ดูผู้สร้าง Multimap) ฉันยังไม่เข้าใจว่าทำไม: มีการเปิดตัวหลายครั้ง แต่ไม่มีการเปลี่ยนแปลงใด ๆ
JeanValjean

27

หากบน Android คุณสามารถใช้สิ่งนี้:

String ext = android.webkit.MimeTypeMap.getFileExtensionFromUrl(file.getName());

โปรดทราบว่าสิ่งนี้จะไม่ทำงานหากสตริงไม่ได้เข้ารหัส (เช่นมีช่องว่างหรืออักขระภาษาจีน) โปรดดู: stackoverflow.com/a/14321470/1074998
Fruit

14

เพื่อที่จะคำนึงถึงชื่อไฟล์ที่ไม่มีตัวอักษรก่อนถึงจุดคุณจะต้องใช้รูปแบบเล็กน้อยของคำตอบที่ยอมรับ

String extension = "";

int i = fileName.lastIndexOf('.');
if (i >= 0) {
    extension = fileName.substring(i+1);
}

"file.doc" => "doc"
"file.doc.gz" => "gz"
".doc" => "doc"

อาจจะป้องกันตัวเองจาก "foo" อินพุต
chrisinmtown

14

นี่เป็นวิธีทดสอบ

public static String getExtension(String fileName) {
    char ch;
    int len;
    if(fileName==null || 
            (len = fileName.length())==0 || 
            (ch = fileName.charAt(len-1))=='/' || ch=='\\' || //in the case of a directory
             ch=='.' ) //in the case of . or ..
        return "";
    int dotInd = fileName.lastIndexOf('.'),
        sepInd = Math.max(fileName.lastIndexOf('/'), fileName.lastIndexOf('\\'));
    if( dotInd<=sepInd )
        return "";
    else
        return fileName.substring(dotInd+1).toLowerCase();
}

และกรณีทดสอบ:

@Test
public void testGetExtension() {
    assertEquals("", getExtension("C"));
    assertEquals("ext", getExtension("C.ext"));
    assertEquals("ext", getExtension("A/B/C.ext"));
    assertEquals("", getExtension("A/B/C.ext/"));
    assertEquals("", getExtension("A/B/C.ext/.."));
    assertEquals("bin", getExtension("A/B/C.bin"));
    assertEquals("hidden", getExtension(".hidden"));
    assertEquals("dsstore", getExtension("/user/home/.dsstore"));
    assertEquals("", getExtension(".strange."));
    assertEquals("3", getExtension("1.2.3"));
    assertEquals("exe", getExtension("C:\\Program Files (x86)\\java\\bin\\javaw.exe"));
}

10

ฉันสกปรกและอาจเล็กที่สุดโดยใช้String.replaceAll :

.replaceAll("^.*\\.(.*)$", "$1")

โปรดทราบว่าครั้งแรก*เป็นโลภดังนั้นมันจะคว้าตัวละครที่เป็นไปได้มากที่สุดเท่าที่จะทำได้แล้วเพียงแค่จุดสุดท้ายและนามสกุลไฟล์จะถูกทิ้งไว้


สิ่งนี้จะล้มเหลวหากไฟล์นั้นไม่มีนามสกุล
แซค

ได้ แต่น่าเสียดายที่ยังสามารถใช้สำหรับสถานการณ์แบบง่าย ๆ เช่นการตรวจจับประเภทไฟล์อย่างรวดเร็วและเช่นการมีส่วนขยายที่ไม่ถูกต้องนั้นไม่แตกต่างจากการไม่มีเลยหรือมีเงื่อนไขว่าเมื่อผลลัพธ์ของการแทนที่เท่ากับอินพุต
Ebrahim Byagowi

1
หรือสั้นกว่านั้น.replaceAll(".*\\.", "")
Ebrahim Byagowi

10
String path = "/Users/test/test.txt";
String extension = "";

if (path.contains("."))
     extension = path.substring(path.lastIndexOf("."));

ส่งคืน ".txt"

ถ้าคุณต้องการเพียง "txt" ทำ path.lastIndexOf(".") + 1


9

เห็นได้ชัดจากคำตอบอื่น ๆ ทั้งหมดไม่มีฟังก์ชั่น "ในตัว" ที่เพียงพอ นี่เป็นวิธีที่ปลอดภัยและเรียบง่าย

String getFileExtension(File file) {
    if (file == null) {
        return "";
    }
    String name = file.getName();
    int i = name.lastIndexOf('.');
    String ext = i > 0 ? name.substring(i + 1) : "";
    return ext;
}

7

วิธีการเกี่ยวกับ (โดยใช้ Java 1.5 RegEx):

    String[] split = fullFileName.split("\\.");
    String ext = split[split.length - 1];

6

หากคุณวางแผนที่จะใช้ Apache Commons-io และเพียงต้องการตรวจสอบส่วนขยายของไฟล์จากนั้นทำการดำเนินการบางอย่างคุณสามารถใช้สิ่งนี้ได้นี่คือตัวอย่าง:

if(FilenameUtils.isExtension(file.getName(),"java")) {
    someoperation();
}

โปรดทราบว่าการตรวจสอบนี้เป็นกรณี ๆ ไปตามเอกสาร
Babken Vardanyan

6

นี่เป็นอีกหนึ่งซับสำหรับ Java 8

String ext = Arrays.stream(fileName.split("\\.")).reduce((a,b) -> b).orElse(null)

มันทำงานได้ดังต่อไปนี้:

  1. แยกสตริงออกเป็นอาร์เรย์ของสตริงโดยใช้ "."
  2. แปลงอาร์เรย์เป็นสตรีม
  3. ใช้ลดเพื่อรับองค์ประกอบสุดท้ายของสตรีมเช่นนามสกุลไฟล์

4

แล้ว JFileChooser ล่ะ? ไม่ตรงไปตรงมาเพราะคุณจะต้องแยกวิเคราะห์ผลลัพธ์สุดท้าย ...

JFileChooser filechooser = new JFileChooser();
File file = new File("your.txt");
System.out.println("the extension type:"+filechooser.getTypeDescription(file));

ประเภท MIME คือ ...

ตกลง ... ฉันลืมว่าคุณไม่ต้องการรู้ประเภท MIME

รหัสที่น่าสนใจในลิงค์ต่อไปนี้: http://download.oracle.com/javase/tutorial/uiswing/components/filechooser.html

/*
 * Get the extension of a file.
 */  
public static String getExtension(File f) {
    String ext = null;
    String s = f.getName();
    int i = s.lastIndexOf('.');

    if (i > 0 &&  i < s.length() - 1) {
        ext = s.substring(i+1).toLowerCase();
    }
    return ext;
}

คำถามที่เกี่ยวข้อง: ฉันจะตัดแต่งนามสกุลไฟล์จาก String ใน Java ได้อย่างไร


4

นี่คือวิธีการที่จัดการ.tar.gzอย่างเหมาะสมแม้ในเส้นทางที่มีจุดในชื่อไดเรกทอรี:

private static final String getExtension(final String filename) {
  if (filename == null) return null;
  final String afterLastSlash = filename.substring(filename.lastIndexOf('/') + 1);
  final int afterLastBackslash = afterLastSlash.lastIndexOf('\\') + 1;
  final int dotIndex = afterLastSlash.indexOf('.', afterLastBackslash);
  return (dotIndex == -1) ? "" : afterLastSlash.substring(dotIndex + 1);
}

afterLastSlashถูกสร้างขึ้นเพื่อให้ค้นหาafterLastBackslashได้เร็วขึ้นเนื่องจากจะไม่ต้องค้นหาสตริงทั้งหมดหากมีเครื่องหมายทับบางส่วนอยู่

char[]ภายในเดิมStringจะถูกนำกลับมาใช้เพิ่มขยะที่นั่นและJVM ที่อาจจะสังเกตเห็นว่าafterLastSlashเป็นขยะทันทีเพื่อที่จะใส่ไว้ในสแต็คแทนของกอง


วิธีนี้ถูกคัดลอกมาจากรหัสที่มาของ Guava คุณต้องพูดถึงสิ่งนี้
อับอาย

1
ฉันไม่ได้คัดลอกสิ่งนี้ หากอยู่ในซอร์สโค้ดของ Guava พวกเขาก็คัดลอกมาจากที่นี่ อาจแจ้งให้พวกเขา
โอเลเท

ขออภัยที่ไม่เหมือนกัน btw ดังนั้นคุณและ Guava dev อาจมีความคิดเดียวกัน
humished

2
จริง ๆ "gz" เป็นส่วนขยายที่ถูกต้องเพื่อส่งคืน หากรหัสการโทรสามารถจัดการ "tar" ได้ก็ควรตรวจสอบเพิ่มเติมภายนอกกับgetExtensionฟังก์ชัน หากชื่อไฟล์ของผู้ใช้เป็น"my zip. don't touch.tar.gz"วิธีการนี้จะส่งคืนนามสกุลที่ไม่ถูกต้อง
intrepidis

2
// Modified from EboMike's answer

String extension = "/path/to/file/foo.txt".substring("/path/to/file/foo.txt".lastIndexOf('.'));

ส่วนขยายควรมี ".txt" อยู่ในส่วนขยายเมื่อเรียกใช้


13
จะล้มเหลวหากชื่อไม่มีส่วนขยาย
EboMike

2

นี่คือรุ่นที่มีตัวเลือกเป็นค่าส่งคืน (ทำให้คุณไม่แน่ใจว่าไฟล์นั้นมีนามสกุล) ... ยังมีสติตรวจสอบ ...

import java.io.File;
import java.util.Optional;

public class GetFileExtensionTool {

    public static Optional<String> getFileExtension(File file) {
        if (file == null) {
            throw new NullPointerException("file argument was null");
        }
        if (!file.isFile()) {
            throw new IllegalArgumentException("getFileExtension(File file)"
                    + " called on File object that wasn't an actual file"
                    + " (perhaps a directory or device?). file had path: "
                    + file.getAbsolutePath());
        }
        String fileName = file.getName();
        int i = fileName.lastIndexOf('.');
        if (i > 0) {
            return Optional.of(fileName.substring(i + 1));
        } else {
            return Optional.empty();
        }
    }
}

2

แล้วรุ่นREGEX ล่ะ :

static final Pattern PATTERN = Pattern.compile("(.*)\\.(.*)");

Matcher m = PATTERN.matcher(path);
if (m.find()) {
    System.out.println("File path/name: " + m.group(1));
    System.out.println("Extention: " + m.group(2));
}

หรือสนับสนุนนามสกุล null:

static final Pattern PATTERN =
    Pattern.compile("((.*\\" + File.separator + ")?(.*)(\\.(.*)))|(.*\\" + File.separator + ")?(.*)");

class Separated {
    String path, name, ext;
}

Separated parsePath(String path) {
    Separated res = new Separated();
    Matcher m = PATTERN.matcher(path);
    if (m.find()) {
        if (m.group(1) != null) {
            res.path = m.group(2);
            res.name = m.group(3);
            res.ext = m.group(5);
        } else {
            res.path = m.group(6);
            res.name = m.group(7);
        }
    }
    return res;
}


Separated sp = parsePath("/root/docs/readme.txt");
System.out.println("path: " + sp.path);
System.out.println("name: " + sp.name);
System.out.println("Extention: " + sp.ext);

ผลลัพธ์สำหรับ * nix:
path: / root / docs /
name: readme
Extention: txt

สำหรับ windows, parsePath ("c: \ windows \ readme.txt"):
พา ธ : c: \ windows \
name: readme
Extention: txt



1

ที่นี่ฉันทำวิธีเล็ก ๆ (แต่ไม่ปลอดภัยและไม่ได้ตรวจสอบข้อผิดพลาดจำนวนมาก) แต่ถ้าเป็นเพียงคุณเท่านั้นที่เขียนโปรแกรมจาวาทั่วไปโปรแกรมนี้เป็นมากกว่าเพียงพอที่จะหาไฟล์ประเภท สิ่งนี้ใช้ไม่ได้กับประเภทไฟล์ที่ซับซ้อน แต่โดยทั่วไปจะไม่ได้ใช้งานมากนัก

    public static String getFileType(String path){
       String fileType = null;
       fileType = path.substring(path.indexOf('.',path.lastIndexOf('/'))+1).toUpperCase();
       return fileType;
}

OP กำลังมองหาวิธีการในตัว
Panther

(1) คุณควรใช้lastIndexOfเพื่อให้ชื่อไฟล์เช่นjohn.smith.report.docนั้นได้รับการปฏิบัติอย่างเหมาะสม (2) คุณควรจัดการกรณีอย่างถูกต้องเมื่อไม่มีส่วนขยาย วิธีนี้จะคืนค่าABC/XYZเส้นทางเหมือนabc/xyzซึ่งไม่สมเหตุสมผล มันจะทำให้รู้สึกมากขึ้นที่จะกลับมาหรือ"" null(3) คั่นไฟล์ไม่เสมอ /
Radiodef

1

รับนามสกุลไฟล์จากชื่อไฟล์

/**
 * The extension separator character.
 */
private static final char EXTENSION_SEPARATOR = '.';

/**
 * The Unix separator character.
 */
private static final char UNIX_SEPARATOR = '/';

/**
 * The Windows separator character.
 */
private static final char WINDOWS_SEPARATOR = '\\';

/**
 * The system separator character.
 */
private static final char SYSTEM_SEPARATOR = File.separatorChar;

/**
 * Gets the extension of a filename.
 * <p>
 * This method returns the textual part of the filename after the last dot.
 * There must be no directory separator after the dot.
 * <pre>
 * foo.txt      --> "txt"
 * a/b/c.jpg    --> "jpg"
 * a/b.txt/c    --> ""
 * a/b/c        --> ""
 * </pre>
 * <p>
 * The output will be the same irrespective of the machine that the code is running on.
 *
 * @param filename the filename to retrieve the extension of.
 * @return the extension of the file or an empty string if none exists.
 */
public static String getExtension(String filename) {
    if (filename == null) {
        return null;
    }
    int index = indexOfExtension(filename);
    if (index == -1) {
        return "";
    } else {
        return filename.substring(index + 1);
    }
}

/**
 * Returns the index of the last extension separator character, which is a dot.
 * <p>
 * This method also checks that there is no directory separator after the last dot.
 * To do this it uses {@link #indexOfLastSeparator(String)} which will
 * handle a file in either Unix or Windows format.
 * <p>
 * The output will be the same irrespective of the machine that the code is running on.
 *
 * @param filename  the filename to find the last path separator in, null returns -1
 * @return the index of the last separator character, or -1 if there
 * is no such character
 */
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);
}

/**
 * Returns the index of the last directory separator character.
 * <p>
 * This method will handle a file in either Unix or Windows format.
 * The position of the last forward or backslash is returned.
 * <p>
 * The output will be the same irrespective of the machine that the code is running on.
 *
 * @param filename  the filename to find the last path separator in, null returns -1
 * @return the index of the last separator character, or -1 if there
 * is no such character
 */
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);
}

เครดิต

  1. คัดลอกมาจาก Apache FileNameUtils Class - http://grepcode.com/file/repo1.maven.org/maven2/commons-io/commons-io/1.3.2/org/apache/commons/io/FilenameUtils.java#FilenameUtils getExtension% 28java.lang.String 29%

1

โดยไม่ต้องใช้ไลบรารีใด ๆ คุณสามารถใช้การแยกเมธอด String ดังนี้:

        String[] splits = fileNames.get(i).split("\\.");

        String extension = "";

        if(splits.length >= 2)
        {
            extension = splits[splits.length-1];
        }

0

เป็นเพียงทางเลือกที่ใช้นิพจน์ทั่วไป ไม่เร็วขนาดนั้นไม่ดี

Pattern pattern = Pattern.compile("\\.([^.]*)$");
Matcher matcher = pattern.matcher(fileName);

if (matcher.find()) {
    String ext = matcher.group(1);
}

0

ฉันพบวิธีที่ดีกว่าในการค้นหาส่วนขยายโดยการผสมคำตอบทั้งหมดข้างต้น

public static String getFileExtension(String fileLink) {

        String extension;
        Uri uri = Uri.parse(fileLink);
        String scheme = uri.getScheme();
        if (scheme != null && scheme.equals(ContentResolver.SCHEME_CONTENT)) {
            MimeTypeMap mime = MimeTypeMap.getSingleton();
            extension = mime.getExtensionFromMimeType(CoreApp.getInstance().getContentResolver().getType(uri));
        } else {
            extension = MimeTypeMap.getFileExtensionFromUrl(fileLink);
        }

        return extension;
    }

public static String getMimeType(String fileLink) {
        String type = CoreApp.getInstance().getContentResolver().getType(Uri.parse(fileLink));
        if (!TextUtils.isEmpty(type)) return type;
        MimeTypeMap mime = MimeTypeMap.getSingleton();
        return mime.getMimeTypeFromExtension(FileChooserUtil.getFileExtension(fileLink));
    }

0

ฉันชอบความเรียบง่ายของคำตอบของสเปคตรัมและลิงก์ในหนึ่งในความคิดเห็นของเขาคือลิงก์ไปยังคำตอบอื่นที่แก้ไขจุดในเส้นทางของไฟล์ในคำถามอื่นโดย EboMikeEboMike

โดยไม่ใช้ API ของบุคคลที่สามฉันแนะนำ:

private String getFileExtension(File file) {

    String name = file.getName().substring(Math.max(file.getName().lastIndexOf('/'),
            file.getName().lastIndexOf('\\')) < 0 ? 0 : Math.max(file.getName().lastIndexOf('/'),
            file.getName().lastIndexOf('\\')));
    int lastIndexOf = name.lastIndexOf(".");
    if (lastIndexOf == -1) {
        return ""; // empty extension
    }
    return name.substring(lastIndexOf + 1); // doesn't return "." with extension
}

บางอย่างเช่นนี้อาจจะมีประโยชน์ในการพูดใด ๆ ของ ImageIO ของwriteวิธีการที่รูปแบบไฟล์ที่จะต้องมีการส่งผ่านไปใน

เหตุใดจึงต้องใช้ API บุคคลที่สามทั้งหมดเมื่อคุณสามารถ DIY ได้


0

คำถามนี้ทำให้ฉันมีปัญหามากแล้วฉันก็พบวิธีแก้ปัญหาง่ายๆที่ฉันโพสต์ที่นี่

file.getName().toLowerCase().endsWith(".txt");

แค่นั้นแหละ.


3
OP ต้องการวิธีแยกส่วนขยาย - ไม่ต้องทดสอบส่วนขยาย
Predrag Manojlovic

จริงๆแล้วอะไรก็ตามที่คุณกำลังพัฒนาในกรณีส่วนใหญ่คุณต้องจัดการกับไฟล์บางประเภทเท่านั้น .. ดังนั้นหากปัญหาของคุณมาถึงในส่วนนี้สิ่งนี้จะช่วยคุณได้
Vikram Bhardwaj

4
ซึ่งไม่ตรงกับความต้องการของเขา
Predrag Manojlovic

2
นี่ไม่ใช่คำตอบสำหรับคำถามนี้ แต่นี่คือสิ่งที่ฉันกำลังมองหา
Ediolot

-1

ลองนี้

String[] extension = "adadad.adad.adnandad.jpg".split("\\.(?=[^\\.]+$)"); // ['adadad.adad.adnandad','jpg']
extension[1] // jpg

-1
  @Test
    public void getFileExtension(String fileName){
      String extension = null;
      List<String> list = new ArrayList<>();
      do{
          extension =  FilenameUtils.getExtension(fileName);
          if(extension==null){
              break;
          }
          if(!extension.isEmpty()){
              list.add("."+extension);
          }
          fileName = FilenameUtils.getBaseName(fileName);
      }while (!extension.isEmpty());
      Collections.reverse(list);
      System.out.println(list.toString());
    }

-4

Java มีวิธีจัดการกับสิ่งนี้ในตัวในคลาส java.nio.file.Filesที่อาจทำงานได้ตามความต้องการของคุณ:

File f = new File("/path/to/file/foo.txt");
String ext = Files.probeContentType(f.toPath());
if(ext.equalsIgnoreCase("txt")) do whatever;

โปรดทราบว่าวิธีการแบบคงที่นี้ใช้ข้อกำหนดที่พบที่นี่เพื่อดึง "ประเภทเนื้อหา" ซึ่งสามารถแตกต่างกันไป


28
สิ่งนี้ไม่ถูกต้อง ชนิดส่งคืนสำหรับ probeContentType คือชนิดเนื้อหา Mime ไม่ใช่นามสกุลไฟล์ โดยปกติจะไม่ตรงกับส่วนขยาย สิ่งนี้จะค่อนข้างช้าในเบราว์เซอร์ไฟล์เนื่องจากจริง ๆ แล้วเปิดไฟล์เพื่อกำหนดประเภท
ชาร์ลส์
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.