Java: dosya adını bir tabana ve uzantıya bölme


83

Dosya taban adını ve uzantısını almanın şunun gibi bir şeyden daha iyi bir yolu var mı?

File f = ...
String name = f.getName();
int dot = name.lastIndexOf('.');
String base = (dot == -1) ? name : name.substring(0, dot);
String extension = (dot == -1) ? "" : name.substring(dot+1);

7
Commons-io'ya bir göz atın FilenameUtils. Bu sahiptir getBaseName(..)ve getExtension(..)yöntemler.
Bozho

Yanıtlar:


168

Başkalarının bahsettiğini biliyorum String.split, ancak burada yalnızca iki jeton (temel ve uzantı) veren bir varyant var :

String[] tokens = fileName.split("\\.(?=[^\\.]+$)");

Örneğin:

"test.cool.awesome.txt".split("\\.(?=[^\\.]+$)");

Verimler:

["test.cool.awesome", "txt"]

Normal ifade, Java'ya herhangi bir sayıda nokta olmayan dönemlerin ve ardından girdinin sonunun geldiği herhangi bir döneme bölünmesini söyler. Bu tanıma uyan tek bir dönem vardır (yani son dönem).

Teknik olarak Regexical olarak konuşursak, bu tekniğe sıfır genişlikli pozitif bakış açısı denir .


BTW, bir yolu bölmek ve nokta uzantısı dahil ancak bununla sınırlı olmamak üzere tam dosya adını almak istiyorsanız, eğik çizgi içeren bir yol kullanarak,

    String[] tokens = dir.split(".+?/(?=[^/]+$)");

Örneğin:

    String dir = "/foo/bar/bam/boozled"; 
    String[] tokens = dir.split(".+?/(?=[^/]+$)");
    // [ "/foo/bar/bam/" "boozled" ] 

2
İnsanların bağımlılıklardan neden korktuğu hakkında hiçbir fikrim yok ;-)
Bozho

3
@Bozho: Kütüphanelerin bu tür problemler için daha iyi çözümler olduğuna katılıyorum. Başkalarının bakımını ve sizin için düşünmesini sağlar (bu yüzden cevabınızı yukarı oyladım!). Bu önemsiz gelebilir, ancak bir Apache kitaplığı eklemeyi düşündüğümde her zaman tereddüt eden bir parçam var çünkü geçmişte bazı şeyleriyle "JAR cehennemi" yaşadım (biliyorum, bu önemsiz).
Adam Paynter

4
@Bozho: Adam% 100 haklı. Bu sorun, başka bir kitaplık almam için yeterli olmazdı - ancak zaten başka nedenlerle commons-io kullanıyor olsaydım, o zaman Filenameutils'i kullanırdım.
Jason S

1
@ Jason: Düzenli ifadeler: vermeye devam eden hediye. :)
Adam Paynter

3
@Bozho - Alaycılık? Asıl soru, java'nın neden gerçekten yapmak istediğiniz şeyi yapmayı kolaylaştırmaya çok yaklaşan, ama sonra sinir bozucu bir şekilde aslında asla yapmayan gereksiz fazlalık sınıf yığınlarıyla geldiği. Python'da Apache-Commons'ın eşdeğeri yoktur çünkü Python, zaten yerleşik olmasını istediğiniz tüm yararlı şeylere sahiptir. C #, tekerleği nasıl yeniden icat edeceğinizi veya başka birinin icat ettiği tekerleği nasıl alacağınızı bulmak yerine benzersiz probleminize odaklanabileceğiniz başka bir dil örneği gibi görünüyor.
ArtOfWarfare

84

Eski soru ama genellikle bu çözümü kullanıyorum:

import org.apache.commons.io.FilenameUtils;

String fileName = "/abc/defg/file.txt";

String basename = FilenameUtils.getBaseName(fileName);
String extension = FilenameUtils.getExtension(fileName);
System.out.println(basename); // file
System.out.println(extension); // txt (NOT ".txt" !)

Windows'ta çalışmak ve "dosyaAdı" Dizesi "D: \ kaynaklar \ ftp_upload.csv" ise işe yaramaz. Lütfen yardımcı olabilir misiniz?
NIKHIL CHAURASIA

3
@NIKHILCHAURASIA ters eğik çizgileri ikiye katlayarak kaçmanız gerekir. Gibi: "D: \\ kaynaklar \\ ftp_upload.csv".
Ricket

8

Kaynak: http://www.java2s.com/Code/Java/File-Input-Output/Getextensionpathandfilename.htm

böyle bir yardımcı sınıf:

class Filename {
  private String fullPath;
  private char pathSeparator, extensionSeparator;

  public Filename(String str, char sep, char ext) {
    fullPath = str;
    pathSeparator = sep;
    extensionSeparator = ext;
  }

  public String extension() {
    int dot = fullPath.lastIndexOf(extensionSeparator);
    return fullPath.substring(dot + 1);
  }

  public String filename() { // gets filename without extension
    int dot = fullPath.lastIndexOf(extensionSeparator);
    int sep = fullPath.lastIndexOf(pathSeparator);
    return fullPath.substring(sep + 1, dot);
  }

  public String path() {
    int sep = fullPath.lastIndexOf(pathSeparator);
    return fullPath.substring(0, sep);
  }
}

kullanım:

public class FilenameDemo {
  public static void main(String[] args) {
    final String FPATH = "/home/mem/index.html";
    Filename myHomePage = new Filename(FPATH, '/', '.');
    System.out.println("Extension = " + myHomePage.extension());
    System.out.println("Filename = " + myHomePage.filename());
    System.out.println("Path = " + myHomePage.path());
  }
}

4
basename()Daha iyi bir ad yerine olurdufilename()
nimcap

uzantı olmaması durumunda (örneğin, "/ etc / hosts" gibi dosya adı) bu, uzantı olarak "ana bilgisayarlar" ı döndürür ("" yerine). kütüphane düzeyinde hizmet sınıfları, köşe durumlarıyla ilgilenmelidir.
Zach-M

6

http://docs.oracle.com/javase/6/docs/api/java/io/File.html#getName ()

Gönderen http://www.xinotes.org/notes/note/774/ :

Java, belirli bir dosya yolunun temel adını ve dizin adını almak için yerleşik işlevlere sahiptir, ancak işlev adları o kadar belirgin değildir.

import java.io.File;

public class JavaFileDirNameBaseName {
    public static void main(String[] args) {
    File theFile = new File("../foo/bar/baz.txt");
    System.out.println("Dirname: " + theFile.getParent());
    System.out.println("Basename: " + theFile.getName());
    }
}

5
java.io.File.getName (), uzantıya sahip adı döndürür.
Bram

2
"Uzantı" diye bir şey olmadığını düşünmeyi tercih ederim :-)

4

Dosya uzantıları bozuk bir kavramdır

Ve orada var bunun için güvenilir bir fonksiyonu. Örneğin bu dosya adını düşünün:

archive.tar.gz

Ne olduğunu uzantısı? DOS kullanıcıları adı tercih ederdi archive.tgz. Bazen , önce dosyayı açan (bir dosya veren ) aptal Windows uygulamaları görürsünüz .tar, ardından arşiv içeriğini görmek için tekrar açmanız gerekir.

Bu durumda, daha makul bir dosya uzantısı kavramı olurdu .tar.gz. Orada da .tar.bz2, .tar.xz, .tar.lzve .tar.lzmadosya "uzantıları" kullanımda. Ama son noktaya mı yoksa ikinci noktadan son noktaya mı ayıracağınıza nasıl karar verirsiniz?

Bunun yerine mime türlerini kullanın.

Java 7 işlevi Files.probeContentType , dosya türlerini algılamak için dosya uzantısına güvenmekten çok daha güvenilir olacaktır. Hemen hemen tüm Unix / Linux dünyası ve Web Tarayıcınız ve Akıllı Telefonunuz zaten bu şekilde yapıyor.


6
Bu soruya nasıl cevap veriyor? Uzantıyı ne Filede bölmeme Pathizin ver.
Andreas Abel

@ andreas.abel şunu tekrar etmeme izin verin: Dosya uzantıları bozuk bir kavramdır. Ne güvenilir ne de DOS 8 + 3 dosya isimleri dışında iyi tanımlanmışlardır ( unix'te çok yaygın olanlara .tar.gzkarşı düşünün .tgz). Bunun yerine mime türlerini kullanın.
ÇIKTI - Anony-Mousse

1
@ Anony-Mousse Evet, prensipte katılıyorum ama etkileşimde bulunduğum tüm sistemlerin% 99,999'u bir dosya adı kullanıyor, bir mim türü değil
Christian Sauer

Files.probeContentTypeDoğru uzantıya sahip olmak için dosya adına güvenmek yerine kullanmanın sorunu nerede ?
ÇIKTI - Anony-Mousse

3
Bu soruya cevap vermiyor. Dosya adının, filmin, ad + uzantı olduğu bir kullanım durumum var. Mime türlerini kullanarak adı nasıl çıkarabilirim?
Niek

1

Kodunuzun nesi var? Düzgün bir yardımcı yöntemle sarılmış, sorun değil.

Daha da önemlisi, ayırıcı olarak neyin kullanılması gerektiğidir - ilk veya son nokta. İlki "setup-2.5.1.exe" gibi dosya adları için kötü, sonuncusu "mybundle.tar.gz" gibi birden çok uzantıya sahip dosya adları için kötüdür.



-3

Belki String # split kullanabilirsiniz

Yorumunuzu cevaplamak için:

Birden fazla olabileceğinden emin değilim. bir dosya adında, ancak her neyse, daha fazla nokta olsa bile bölmeyi kullanabilirsiniz. Örneğin şunu düşünün:

String input = "boo.and.foo";

String[] result = input.split(".");

Bu, şunları içeren bir dizi döndürür:

{ "boo", "and", "foo" }

Böylece dizideki son dizinin uzantı olduğunu ve diğerlerinin de taban olduğunu bileceksiniz.


evet, ama .bir dizedeki sonuncusu için bir normal ifade bulmalıyım
Jason S

1
Hmm emin değilim ama "." Kullanamaz mısın? Veya bir dosya adında 1'den fazla nokta mı var?

2
Bunun işe yarayacağını düşünüyorum:fileName.split("\\.(?=[^\\.]+$)")
Adam Paynter

1
Yalnızca bir nokta olduğunu varsayamazsınız. Adam: teşekkürler, deneyeceğim.
Jason S

4
Bu cevap yanlıştır. Nokta kaçmadığından boş bir dizi döndürecektir.
aled
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.