Javaでファイルのファイル拡張子を取得するにはどうすればよいですか?


484

明確にするために、私はMIMEタイプを探していません。

次の入力があるとします。 /path/to/file/foo.txt

この入力を、特に.txt拡張機能に分割する方法を教えてください。これをJavaで行うための組み込みの方法はありますか?自分のパーサーを書くことは避けたいです。


12
コンマで区切られた拡張機能を定義する新しいプラットフォームがいつ登場するかは、決してわかりません。次に、プラットフォームに依存するコードを記述する必要があります。Javaフレームワークは、より前向きで、プラットフォームに依存するコードを記述して拡張機能を取得するためのAPIを備えている必要があります。APIのユーザーは、拡張機能を取得するだけです。
ArtOfWarfare 2013年

@ArtOfWarfare:OMG。何千ものクラスを持つ100MBのJREを作成してみましょう。ただし、どこかで使用したいプラットフォーム"txt"がある"filename.txt"ので、から戻るメソッドを実装しないでください"filename,txt"
Eric Duminil

@EricDuminil "「filename.txt」から「txt」を返すメソッドを実装しないでください??? 試してみましょうpath.substring(path.lastIndexOf("."));.....そして、ええ..彼らは間違いなく何かを複製しないでください...
VelocityPulse

@VelocityPulseそれがまさに私を悩ませていることです。ファイル拡張子を取得する標準的な方法はないため、何十通りもの間違った答えとわずかに異なる実装が得られます。あなたのコードは(私が持っていたかった2つの方法使用する1つの、明示的な方法が)、それは返す".txt"から、"filename.txt"望ましい結果ではないかもしれない、と、すべての最悪のは、それがで失敗するStringIndexOutOfBoundsException代わりに拡張子がない場合は、空の文字列を返します。
Eric Duminil

回答:


649

この場合、Apache Commons IOのFilenameUtils.getExtensionを使用します。

これを使用する方法の例を次に示します(フルパスまたはファイル名のみを指定できます)。

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
archive.tar.gzという名前のファイルに対しては「gz」のみを返すことに注意してください。
Zitrax 2014

106
@Zitraxは、「gz」がファイル拡張子であるためです。
BrainSlugs83 2015

6
@ BrainSlugs83では、「タール」とはどういう意味ですか?
TuGordoBello 2016年

31
@zhelon .gzはgnu zipファイルを表し、.tarは(t)ape(ar)chiveを表します。したがって、.tar.gzは、拡張子が.gzのgnu zipファイル内のtarファイルです。
cirovladimir 2016年

5
この単純なタスクのために別のライブラリを持ち込む必要はありません。
masterwok 2018

311

これには本当に「パーサー」が必要ですか?

String extension = "";

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

のようなものではなく、単純なWindowsのようなファイル名を扱っていると仮定しますarchive.tar.gz

ところで、ディレクトリに '。'が含まれている可能性があるが、ファイル名自体が(のように/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
ありがとう!確かに、拡張子だけではなく、より多くの操作をしたい場合は、パーサー/オブジェクトが必要になるかもしれません...パス、親ディレクトリ、ファイル名(拡張子を除いたもの)だけが欲しい場合など。 :私たちは、この持っているC#と.NETから来るメートルmsdn.microsoft.com/en-us/library/...
longda

10
あなたが言うように、単純なlastIndexOf( "。")を使用するだけでなく、考えなければならないことがたくさんあります。Apache Commonsにはこのための方法があり、少しトリッキーな潜在的な問題をすべて考慮に入れていると思います。
MatrixFrog 2010

12
またはi > 0に変更する必要があると思います。これはのようなファイル名を扱います。i >= 0i != -1.htaccess
Pijusn 2013

8
コードスニペットがどれほど単純であるかに関係なく...それを更新/維持/テスト/便利な依存関係として利用できるようにする必要があります...そのすべてをすでに実行しているライブラリがあれば、はるかに簡単です
Don Cheadle

2
さらに問題があるのは、ファイルがドットで終わっている場合です。libのほうがいい。if(i> p && i <(fileName.length()-1)){extension = fileName.substring(i + 1);
tgkprog 2015

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
より良い回答と@NickEntinより良いコメント。ピリオド「。」を削除するには ファイルの拡張子から、int lastIndexOf = name.lastIndexOf( "。")+ 1;のようにコーディングできます。
Hanzallah Afgan、2015

11
このアプローチは、一部のケースでは機能しない場合があります。たとえば、/ usr / bin / foo.bar / httpconf
Iman Akbari

8
@ lukasz1985 1.何百ものLinuxパッケージが "init.d"のような名前のディレクトリを作成します。さらに、ドットのないディレクトリがないパスに依存することは安全ではありません。違法ではないためです。覚えていない方法ですが、stackoverflow.com / a / 3571239/2546146にはこの欠陥がないと思います
Iman Akbari

6
@Iman Akbari:getName()はファイル名自体のみを返します。例では「httpconf」になります。
Dreamspace社長2017

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
本当に?ユーティリティが満載の素晴らしいライブラリです。それらのほとんどは、素晴らしいGuava Functionのように、Java8の一部になります。
JeanValjean 2013年

残念ながら、すべての人が使用するライブラリを決定できるわけではありません。古いものではありますが、少なくともApache Commonsがあります。
Lluis Martinez 2014

1
あなたがgetFileExtension実際にソースコードを見れば、それはint dotIndex = fileName.lastIndexOf('.'); return (dotIndex == -1) ? "" : fileName.substring(dotIndex + 1)それほど大したことではありません。また、Files何らかの理由で「不安定」とマークされていることにも注意してください。
Al-Mothafar

@ Al-Mothafarの多くのクラスは不安定とマークされています(マルチマップビルダーを参照)。その理由もわかりません。いくつかのリリースが行われましたが、何も変更されていません。
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 2018

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")

最初*は貪欲であるため、可能な限りほとんどの文字を取得し、最後のドットとファイル拡張子だけを残します。


ファイルに拡張子がない場合、これは失敗します。
Zack

はい、残念ながら、それでも、ファイルタイプの迅速な検出などの単純なシナリオで使用できます。たとえば、拡張子が正しくないことと、拡張子がない場合との違いはそれほど大きくありません。
エブラヒムビャゴウィ2017

1
またはさらに短い.replaceAll(".*\\.", "")
エブラヒム・ビャゴウィ2017

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 2016年

6

これは、Java 8の別のワンライナーです。

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

次のように機能します。

  1. 「。」を使用して文字列を文字列の配列に分割します。
  2. 配列をストリームに変換します
  3. ストリームの最後の要素、つまりファイル拡張子を取得するには、reduceを使用します

4

JFileChooserはどうですか?最終出力を解析する必要があるため、簡単ではありません...

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

これはMIMEタイプです...

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

関連質問: 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);
}

afterLastSlashafterLastBackslashスラッシュが含まれている場合、文字列全体を検索する必要がないため、検索を迅速化するために作成されます。

char[]オリジナルの内部Stringは再利用され、そこにはガベージが追加されません。JVMはafterLastSlash、ヒープではなくスタックに置くために、ガベージであることをすぐに認識します


このメソッドは、あなたがこれに言及しなければならないGuavaソースコードからコピーされます。
2016年

1
これはコピーしませんでした。Guavaのソースコードに含まれている場合は、ここからコピーします。おそらくそれらに通知します。
Olathe

申し訳ありませんが、これはまったく同じではありません。あなたとGuava開発者が同じ考えを持っている可能性があります。
2016年

2
本当に「gz」が正しい拡張子です。呼び出し元のコードが「tar」も処理できる場合は、getExtension関数の外部でさらにチェックする必要があります。ユーザーのファイル名がの場合、"my zip. don't touch.tar.gz"このメソッドは誤った拡張子を返します。
intrepidis 2018

2
// Modified from EboMike's answer

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

実行時に拡張子に「.txt」が含まれている必要があります。


13
名前に拡張子がない場合はクラッシュします。
EboMike 2010

2

これは、戻り値としてOptionalを使用したバージョンです(ファイルに拡張子があるかどうかを確認できないため)...妥当性チェックも...

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

正規表現のバージョンはどうですか:

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の結果:
パス:/ root / docs /
名前:readme
拡張子:txt

Windowsの場合、parsePath( "c:\ windows \ readme.txt"):
パス:c:\ windows \
名前:readme
拡張子:txt



1

ここで私は小さなメソッドを作成しました(ただし、安全ではなく、多くのエラーをチェックしません)。ただし、一般的なJavaプログラムをプログラミングしているのがあなただけの場合、これはファイルタイプを見つけるのに十分です。これは複雑なファイルタイプでは機能しませんが、通常はあまり使用されません。

    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クラスからコピー-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メソッドsplitを使用できます。

        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

私はスペクトルの答えの単純さが好きで、彼のコメントの1つにリンクされているのは、EboMikeによって作成された別の質問で、ファイルパスのドットを修正する別の答えへのリンクです。

なんらかのサードパーティの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メソッドのいずれかで役立つ場合があります

DIYできるのに、なぜサードパーティのAPI全体を使用するのですか?


0

この特定の質問は私に多くのトラブルを与えました、そして私はここに投稿しているこの問題の非常に簡単な解決策を見つけました。

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

それでおしまい。


3
OPは拡張を抽出する方法が必要です-拡張をテストする方法ではありません。
Predrag Manojlovic 2016年

実際に開発しているほとんどの場合、特定の種類のファイルのみを処理する必要があります。問題がこの領域にある場合は、これが役立ちます。
Vikram Bhardwaj

4
これは彼の要件に対応していません
Predrag Manojlovic

2
これは質問への答えではありませんが、これは確かに私が探していたものでした。
エディオロット2017

-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.