(外部ライブラリを含まない)
ファイル名を何も想定せずに、Javaでファイル名の拡張子を削除する最も効率的な方法は何ですか?
いくつかの例と期待される結果:
(または最後のものはちょうどhidden?)
編集:元の質問では、入力がファイル名(ファイルパスではない)であると想定されていました。いくつかの回答はファイルパスについて話しているので、そのような関数は次のような場合にも機能するはずです。
この特定のケースは、SylvainMの回答によって非常にうまく処理されます。
特別な場合のチェックコードを削除し、意図をより読みやすくするために、2引数バージョンのlastIndexOf
を使用するこれを突き刺します。クレジットは Justin'jinguy 'Nelson この方法の基礎を提供するために行きます:
public static String removeExtention(String filePath) {
// These first few lines the same as Justin's
File f = new File(filePath);
// if it's a directory, don't remove the extention
if (f.isDirectory()) return filePath;
String name = f.getName();
// Now we know it's a file - don't need to do any special hidden
// checking or contains() checking because of:
final int lastPeriodPos = name.lastIndexOf('.');
if (lastPeriodPos <= 0)
{
// No period after first character - return name as it was passed in
return filePath;
}
else
{
// Remove the last period and everything after it
File renamed = new File(f.getParent(), name.substring(0, lastPeriodPos));
return renamed.getPath();
}
}
私にとって、これは特殊な隠しファイルやドットを含まないファイルよりも明確です。また、私があなたの仕様を理解していることをより明確に読みます。 「最後のドットとそれに続くすべてのドットが存在し、ファイル名の最初の文字ではないと仮定して、それを削除する」のようなものです。
この例は、入力および出力として文字列も暗示していることに注意してください。ほとんどの抽象化にはFile
オブジェクトが必要なので、それらが入力と出力でもある場合は、わずかに明確になります。
Apacheからの共通ioの使用 http://commons.Apache.org/io/
public static String removeExtension(String filename)
参考までに、ソースコードは次のとおりです。
Arg、私はちょうど何かを試しました...
System.out.println(FilenameUtils.getExtension(".polop")); // polop
System.out.println(FilenameUtils.removeExtension(".polop")); // empty string
したがって、このソリューションはあまり良くないようです...一般的なioを使用しても、removeExtension()getExtension()indexOfExtension()で遊ぶ必要があります...
これはファイルパスを取り、拡張子なしでファイルの新しい名前を返します。
public static String removeExtention(String filePath) {
File f = new File(filePath);
// if it's a directory, don't remove the extention
if (fisDirectory()) return f.getName();
String name = f.getName();
// if it is a hidden file
if (name.startsWith(".")) {
// if there is no extn, do not rmove one...
if (name.lastIndexOf('.') == name.indexOf('.')) return name;
}
// if there is no extention, don't do anything
if (!name.contains(".") return name;
// Otherwise, remove the last 'extension type thing'
return name.substring(0, name.lastIndexOf('.'))
}
これは私のネットブックの小さなSOエディターボックスに書かれていることに注意してください。このコードは本番用ではありません。最初の試みとしてサーバーを使用することのみを目的としています。ファイル名から拡張子を削除する方法の例。
int p=name.lastIndexOf('.');
if (p>0)
name=name.substring(0,p);
「.hidden」の例のように、最初の文字がピリオドの場合、名前全体を消去したくないため、「p> = 0」ではなく「p> 0」と言いました。
ディスク上のファイル名を実際に更新したいですか、それとも内部でファイル名を操作するだけですか?
有効なファイル名があれば、実際には非常に簡単です。
Windowsファイル名では、ドット文字は拡張子を指定するためにのみ使用されます。したがって、ドットとその後のすべてを取り除きます。
UNIXライクなファイル名では、ドットは、最後の区切り文字( '/')の後にあり、最後の区切り文字との間に少なくとも1文字ある場合(区切り文字がない場合は最初の文字ではありません)、拡張子を示します。最後のドットを見つけて、それが条件を満たすかどうかを確認し、満たす場合はそれと末尾の文字を取り除きます。
これを行う前にファイル名を検証することが重要です。これは、invlaidファイル名に対するこのアルゴリズムが予期しないことを行い、有効なファイル名を生成する可能性があるためです。したがって、Windowsでは、ドットの後に円記号やコロンがないことを確認する必要がある場合があります。
扱っているファイル名の種類がわからない場合は、それらをすべてUnixのように扱うことでほとんどの方法が得られます。
新しいRemover()。remove(String)を使用し、
jdb@Vigor14:/tmp/stackoverflow> javac Remover.Java && Java Remover
folder > folder
hello.txt > hello
read.me > read
hello.bkp.txt > hello.bkp
weird..name > weird.
.hidden > .hidden
Remover.Java、
import Java.util.*;
public class Remover {
public static void main(String [] args){
Map<String, String> tests = new LinkedHashMap<String, String>();
tests.put("folder", "folder");
tests.put("hello.txt", "hello");
tests.put("read.me", "read");
tests.put("hello.bkp.txt", "hello.bkp");
tests.put("weird..name", "weird.");
tests.put(".hidden", ".hidden");
Remover r = new Remover();
for(String in: tests.keySet()){
String actual = r.remove(in);
log(in+" > " +actual);
String expected = tests.get(in);
if(!expected.equals(actual)){
throw new RuntimeException();
}
}
}
private static void log(String s){
System.out.println(s);
}
public String remove(String in){
if(in == null) {
return null;
}
int p = in.lastIndexOf(".");
if(p <= 0){
return in;
}
return in.substring(0, p);
}
}
これらの正規表現は十分に「高速」ですが、考えられる最も単純な方法と比較すると効率的ではありません。文字列を最後からスキャンし、最初のドット(包括的ではない)で切り捨てます。 Javaでは、lastIndexOfと部分文字列を使用して、関心のある部分のみを取得できます。最初のドットは特殊なケースと見なされ、「。」の最後の出現が先頭にある場合です。 、文字列全体を返す必要があります。
私はそれを行うための正規表現を知っていますが、Javaで単純な正規表現の置換を行うために10行のコードのように書く必要がありますか?
隠しファイルを強制終了する場合としない場合:
^(.*)\..*$
^(..*)\..*$
filename.replace("$(.+)\.\\w+", "\1");