Javaで文字列からファイル拡張子を削除するにはどうすればよいですか?


176

次のように、Javaでサフィックスをトリミングする最も効率的な方法は何ですか。

title part1.txt
title part2.html
=>
title part1
title part2

2
効率的なコードに関しては、CPUに関してではなく、私が望んでいる意味です
mkoryak

3
彼はそれを行う方法を尋ねていたのではなく、最も効率的な方法は何かを尋ねていました。私は同じことを探してここに来ました。
エドワードフォーク

回答:


285

これは、私たちが自分でやってはいけない種類のコードです。ありふれたものにはライブラリを使用し、難しいもののためにあなたの脳を救ってください。

この場合、私が使用することをお勧めしますFilenameUtils.removeExtension()からのApache CommonsのIOを


7
絶対に強打します。
Joshua Pinter、

6
95%のプロジェクトでは、これが受け入れられる答えになるはずです。このようなコードの書き換えは、多くの頭痛の種となっています。
Carsten Hoffmann 2016

1
依存関係を追加するには、gradleに次の行を追加するだけです。-コンパイル 'commons-io:commons-io:2.6'
Deepak Sharma

例をご覧ください。
john ktejik

8
プロジェクトにすでにApache Commons I / Oがある場合、それは正しいことです。しかし、これで必要なものがすべてあれば、プロジェクトに(少なくとも)2.5 MBの重みを追加して、1行で簡単に実行できるものを作成します。
foo

226
str.substring(0, str.lastIndexOf('.'))

8
strは変更されないため、これは新しい変数に割り当てる必要があります。
Nathan Feger、

51
注意して処理してください。ファイル名にサフィックスがない場合は、例外がスローされます。
アンドレアスドルク

24
archive.tar.bz2はどうですか?
アントニオ、

20
if(str.contains(".")) str.substring(0, str.lastIndexOf('.'))
Nicolas Tyler

6
if(str!= null && str.contains( "。"))str.substring(0、str.lastIndexOf( '。'))。FilenameUtilsは別の依存関係であり、常に利用できるわけではありません
ocramot

88

String.substringおよびString.lastIndexをワンライナーで使用することは良いことなので、特定のファイルパスに対応できるという点でいくつかの問題があります。

たとえば、次のパスを考えてみます。

a.b/c

ワンライナーを使用すると、次の結果になります。

a

不正解です。

結果はであるはずcですが、ファイルには拡張子がなかったため、パスに.名前にaが含まれるディレクトリが含まれていたため、ワンライナーメソッドは、ファイル名としてパスの一部を指定するように騙されましたが、これは正しくありません。

チェックの必要性

skaffmanの回答に触発されて、私はApache Commons IOのFilenameUtils.removeExtensionメソッドを見ました。

その動作を再現するために、私は新しいメソッドが満たすべきいくつかのテストを書きました。それらは次のとおりです。

パスファイル名
-------------- --------
a / b / cc
a / b / c.jpg c
a / b / c.jpg.jpg c.jpg

ab / cc
ab / c.jpg c
ab / c.jpg.jpg c.jpg

cc
c.jpg c
c.jpg.jpg c.jpg

(そして私がチェックしたのはそれだけです-おそらく私が見落としていた他のチェックが存在するはずです。)

実装

以下は、removeExtensionメソッドの私の実装です。

public static String removeExtension(String s) {

    String separator = System.getProperty("file.separator");
    String filename;

    // Remove the path upto the filename.
    int lastSeparatorIndex = s.lastIndexOf(separator);
    if (lastSeparatorIndex == -1) {
        filename = s;
    } else {
        filename = s.substring(lastSeparatorIndex + 1);
    }

    // Remove the extension.
    int extensionIndex = filename.lastIndexOf(".");
    if (extensionIndex == -1)
        return filename;

    return filename.substring(0, extensionIndex);
}

removeExtension上記のテストでこのメソッドを実行すると、上記の結果が得られます。

メソッドは次のコードでテストされました。これはWindowsで実行されたため、パス区切り文字は\であり\Stringリテラルの一部として使用する場合は、でエスケープする必要があります。

System.out.println(removeExtension("a\\b\\c"));
System.out.println(removeExtension("a\\b\\c.jpg"));
System.out.println(removeExtension("a\\b\\c.jpg.jpg"));

System.out.println(removeExtension("a.b\\c"));
System.out.println(removeExtension("a.b\\c.jpg"));
System.out.println(removeExtension("a.b\\c.jpg.jpg"));

System.out.println(removeExtension("c"));
System.out.println(removeExtension("c.jpg"));
System.out.println(removeExtension("c.jpg.jpg"));

結果は次のとおりです。

c
c
c.jpg
c
c
c.jpg
c
c
c.jpg

結果は、メソッドが満たすべきテストで概説されている望ましい結果です。


4
すばらしい答えです。使用するSystem.getProperty("file.separator")だけでなく、使用する特定の理由はありますFile.separatorか?
ハリルタン2013

2
警告:このソリューションでは、Apache Commons IOメソッドとは異なり、拡張だけでなく、前述のパスも削除されます。
DHa 2016

3
これは失敗するようです/path/to/.htaccess
Kuzeko

17

ところで、私の場合、特定の拡張機能を削除する簡単な解決策が必要だったとき、これはおおよそ私がやったことです:

  if (filename.endsWith(ext))
    return filename.substring(0,filename.length() - ext.length());
  else
    return filename;

16
String foo = "title part1.txt";
foo = foo.substring(0, foo.lastIndexOf('.'));

4
いいえ、複数の「。」がある場合があります。lastIndexOf( '。')が必要
Adam Jaskiewicz

-1は、私が使用していたと思った方法を使用しなかった場合。私からの合計は+0になりました。すばやく交換してください!;)
マイケルマイヤーズ

7
String fileName="foo.bar";
int dotIndex=fileName.lastIndexOf('.');
if(dotIndex>=0) { // to prevent exception if there is no dot
  fileName=fileName.substring(0,dotIndex);
}

これはトリックの質問ですか?:p

もっと速い方法のATMは思いつきません。


7

com.google.common.io.FilesプロジェクトがすでにGoogleコアライブラリに依存している場合は、クラスのメソッドを使用します。必要な方法はgetNameWithoutExtensionです。


なぜ誰かが私の答えに反対していますか?
Toby

これはベース名のみを返すため、パスも削除されることに注意してください。google.github.io
guava

6

あなたはこの機能を試すことができます、非常に基本的な

public String getWithoutExtension(String fileFullPath){
    return fileFullPath.substring(0, fileFullPath.lastIndexOf('.'));
}

5

私はcoolbirdの回答が特に便利だと思いました。

しかし、私は最後の結果ステートメントを次のように変更しました:

if (extensionIndex == -1)
  return s;

return s.substring(0, lastSeparatorIndex+1) 
         + filename.substring(0, extensionIndex);

フルパス名を返したいので。

したがって、「C:\ Users \ mroh004.COM \ Documents \ Test \ Test.xml」は次のようになります。 
   「C:\ Users \ mroh004.COM \ Documents \ Test \ Test」ではなく
   "テスト"

5
filename.substring(filename.lastIndexOf('.'), filename.length()).toLowerCase();

3
質問の反対で、長さを渡す必要はありません。引数部分文字列を1つだけ使用してください

4

正規表現を使用します。これは最後のドットとその後のすべてを置き換えます。

String baseName = fileName.replaceAll("\\.[^.]*$", "");

正規表現をプリコンパイルする場合は、Patternオブジェクトを作成することもできます。


1
String[] splitted = fileName.split(".");
String fileNameWithoutExtension = fileName.replace("." + splitted[splitted.length - 1], "");

"\\."「。」として分割する必要があります。正規表現には特別です。
コンパス2014

1

文字列の画像パスで新しいファイルを作成する

String imagePath;
File test = new File(imagePath);
test.getName();
test.getPath();
getExtension(test.getName());


public static String getExtension(String uri) {
        if (uri == null) {
            return null;
        }

        int dot = uri.lastIndexOf(".");
        if (dot >= 0) {
            return uri.substring(dot);
        } else {
            // No extension.
            return "";
        }
    }

1

org.apache.commons.io.FilenameUtilsバージョン2.4は次の答えを出します

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

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

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

public static final char EXTENSION_SEPARATOR = '.';
private static final char UNIX_SEPARATOR = '/';
private static final char WINDOWS_SEPARATOR = '\\';

1
 private String trimFileExtension(String fileName)
  {
     String[] splits = fileName.split( "\\." );
     return StringUtils.remove( fileName, "." + splits[splits.length - 1] );
  }

0

私はこれを望みます:

String title_part = "title part1.txt";
int i;
for(i=title_part.length()-1 ; i>=0 && title_part.charAt(i)!='.' ; i--);
title_part = title_part.substring(0,i);

最後まで「。」まで 次に、部分文字列を呼び出します。

編集:ゴルフではないかもしれませんが、それは効果的です:)


7
基本的に、これがlastIndexOfが行うことです。なぜ車輪を再発明するのですか?
マイケル・マイヤーズ

楽しみのために、そして少し説明的になります。それだけ。(そして私がこれを書いているとき、lastIndexOfを忘れていました)
fmsf

0

ファイル拡張子がない、または複数のファイル拡張子があるシナリオに留意する

ファイル名の例:file | file.txt | file.tar.bz2

/**
 *
 * @param fileName
 * @return file extension
 * example file.fastq.gz => fastq.gz
 */
private String extractFileExtension(String fileName) {
    String type = "undefined";
    if (FilenameUtils.indexOfExtension(fileName) != -1) {
        String fileBaseName = FilenameUtils.getBaseName(fileName);
        int indexOfExtension = -1;
        while (fileBaseName.contains(".")) {
            indexOfExtension = FilenameUtils.indexOfExtension(fileBaseName);
            fileBaseName = FilenameUtils.getBaseName(fileBaseName);
        }
        type = fileName.substring(indexOfExtension + 1, fileName.length());
    }
    return type;
}

0
String img = "example.jpg";
// String imgLink = "http://www.example.com/example.jpg";
URI uri = null;

try {
    uri = new URI(img);
    String[] segments = uri.getPath().split("/");
    System.out.println(segments[segments.length-1].split("\\.")[0]);
} catch (Exception e) {
    e.printStackTrace();
}

これは、imgimgLinkの両方のを出力します


0
public static String removeExtension(String file) {
    if(file != null && file.length() > 0) {
        while(file.contains(".")) {
            file = file.substring(0, file.lastIndexOf('.'));
        }
    }
    return file;
}

これにより、「a.jpg.jpg」が(正しい)「a.jpg」ではなく「a」に変換されます。file.length() > 0チェックの目的は何ですか?
KlausGütter19年

主な質問は「どのように拡張子を削除するのか?」だったので、はい、「a.txt.zip」を「a」に変換し、「。htaccess」を空に変換します。この関数は文字列で機能するため、ファイル名をnullにすることはできませんが、長さを0にすることができます。シンボルを解析する前に、その価値があるかどうかをすばやく確認してください。よろしく。
アレクセイ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.