Удалить расширение имени файла в Java

(без каких-либо внешних библиотек.)

каков наиболее эффективный способ удалить расширение имени файла в Java, не предполагая ничего из имени файла?

некоторые примеры и ожидаемые результаты:

  • Папка > папка
  • Здравствуйте.тхт > привет
  • читать.me > читать
  • Здравствуйте.БКП.txt > Здравствуйте.БКП
  • странно..имя > странно.
  • .крыться> .скрытый

(или последний должен быть просто скрытый?)

редактировать: исходный вопрос предполагал, что вход является именем файла (а не путем к файлу). Поскольку некоторые ответы говорят о путях к файлам, такие функции должны работать в таких случаях, как:

  • редкие.папка / привет > редко.папка / hello

этот конкретный случай очень хорошо обрабатывается ответом Сильвена М.

10 ответов


у меня будет удар по этому, который использует версию с двумя arg lastIndexOf для того, чтобы удалить код проверки специального случая и, надеюсь, сделать намерение более читаемым. Заслуга Джастин 'jinguy' Нельсон для обеспечения основы этого метода:

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 http://commons.apache.org/io/

public static String removeExtension (имя файла строки)

FYI, исходный код здесь:

http://commons.apache.org/proper/commons-io/javadocs/api-release/src-html/org/apache/commons/io/FilenameUtils.html#line.1025

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. Этот код не предназначен для производства. Он предназначен только для сервера как хороший пример первой попытки того, как я буду удалять расширение из имени файла.


Это на самом деле очень просто, предполагая, что у вас есть действительное имя файла.

в именах файлов Windows символ точки используется только для обозначения расширения. Так что уберите точку и все, что после нее.

в unix-подобных именах файлов точка указывает расширение, если она находится после последнего разделителя ( ' / ' ) и имеет по крайней мере один символ между ним и последним разделителем (и не является первым символом, если нет разделителей). Найдите последнюю точку, посмотрите, удовлетворяет ли она условия, и лишить его и любые конечные символы, если это произойдет.

важно, чтобы вы проверили имя файла, прежде чем делать это, так как этот алгоритм на имя файла invlaid может сделать что-то неожиданное и создать допустимое имя файла. Поэтому в Windows вам может потребоваться проверить, что после точки нет обратной косой черты или двоеточия.

Если вы не знаете, с каким именем файла вы имеете дело, рассматривая их все как Unix, вы получите большую часть пути.


int p=name.lastIndexOf('.');
if (p>0)
  name=name.substring(0,p);

Я сказал" p>0 "вместо" p>=0", потому что если первый символ-это период, мы, по-видимому, не хотим стереть все имя, как в вашем ".скрытый" например.

вы действительно хотите обновить имя файла на диске или вы говорите о просто манипулировании им внутри?


регулярное выражение для этих вещей" достаточно быстро", но не эффективно по сравнению с самым простым методом, который можно подумать: сканируйте строку с конца и усеките ее в первой точке (не включительно). В Java вы можете использовать lastIndexOf и подстроку, чтобы принять только ту часть, которая вас интересует. Начальная точка должна рассматриваться как частный случай, и если последнее появление "."это в начале, вся строка должна быть возвращена.


Я знаю регулярное выражение для этого, но в Java мне нужно написать как 10 строк кода, чтобы сделать простую замену регулярного выражения?

С и без убийства скрытые файлы:

^(.*)\..*$
^(..*)\..*$

использовать новый Remover ().удалить(строка),

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

filename.replace("$(.+)\.\w+", "");

на remove() функция выше должна быть переписана для поддержки тестовых случаев, таких как LOST.DIR/myfile.txt

    public static String removeExtension( String in )
{
    int p = in.lastIndexOf(".");
    if ( p < 0 )
        return in;

    int d = in.lastIndexOf( File.separator );

    if ( d < 0 && p == 0 )
        return in;

    if ( d >= 0 && d > p )
        return in;

    return in.substring( 0, p );
}