Jak uzyskać nazwę pliku z ciągu zawierającego bezwzględną ścieżkę pliku?

236

StringZmienna zawiera nazwę pliku C:\Hello\AnotherFolder\The File Name.PDF. Jak uzyskać nazwę pliku tylko The File Name.PDFjako ciąg?

Planowałem podzielić ciąg, ale to nie jest optymalne rozwiązanie.

Sharon Hwk
źródło
w odniesieniu do Issuetracker.google.com/issues/37131215 zostało to naprawione.
Prags

Odpowiedzi:

280

wystarczy użyć File.getName ()

File f = new File("C:\\Hello\\AnotherFolder\\The File Name.PDF");
System.out.println(f.getName());

przy użyciu metod String :

  File f = new File("C:\\Hello\\AnotherFolder\\The File Name.PDF");  
System.out.println(f.getAbsolutePath().substring(f.getAbsolutePath().lastIndexOf("\\")+1));
PermGenError
źródło
Pomocny. Dzięki.
Pooja
Uważaj na nazwy ścieżek za pomocą „/” zamiast „\”
golimar
278

Alternatywne użycie Path(Java 7+):

Path p = Paths.get("C:\\Hello\\AnotherFolder\\The File Name.PDF");
String file = p.getFileName().toString();

Pamiętaj, że podział łańcucha \\zależy od platformy, ponieważ separator plików może się różnić. Path#getNamezajmuje się tym problemem dla ciebie.

assylias
źródło
1
Czy ktoś zrobił porównanie wydajności różnych metod w tym pytaniu?
zmiażdż
@crush Nie sądzę, że Paths.getuzyskuje dostęp do systemu plików, więc nie spodziewałbym się, że wydajność będzie istotnie różna od podłańcucha / indexOf.
assylias
7
Dlaczego nie istnieje na Androidzie? dziwne.
programista Androida
12
Tak, Path radzi sobie z zależnym od platformy problemem slash / backslash, ale tylko jeśli ścieżka do pliku pochodzi z tego samego komputera (lub platformy). Zastanów się: przesyłasz plik Internet Exploreri ma on ścieżkę, "C:\\Hello\\AnotherFolder\\The File Name.PDF"ale kod działa na komputerze z systemem Unix / Linux, a następnie p.getFileName()zwróci całą ścieżkę, nie tylko The File Name.PDF.
nyxz
3
Dzwonienie toString()jest takie dziwne.
PetroCliff
53

Używanie FilenameUtilsw Apache Commons IO :

String name1 = FilenameUtils.getName("/ab/cd/xyz.txt");
String name2 = FilenameUtils.getName("c:\\ab\\cd\\xyz.txt");
Binoy Babu
źródło
5
Myślę, że ten może być najlepszy, ponieważ czasami może być konieczne przetworzenie ścieżki do pliku z innej platformy
ruiruige1991
Jest to najlepsze, ponieważ: Łatwy do odczytania, najbardziej niezawodny, mniej zbędnych obiektów w kodzie +1
fl0w
32

Biorąc pod uwagę Stringpytanie, o które pytasz, jest

C:\Hello\AnotherFolder\The File Name.PDF

musimy wyodrębnić wszystko po ostatnim separatorze, tj. \. To nas interesuje.

Możesz to zrobić

String fullPath = "C:\\Hello\\AnotherFolder\\The File Name.PDF";
int index = fullPath.lastIndexOf("\\");
String fileName = fullPath.substring(index + 1);

Pozwoli to odzyskać indeks ostatniego \w swoim Stringi ekstrakt z wszystkiego, co przychodzi po niego do fileName.

Jeśli masz Stringinny separator, dostosuj, lastIndexOfaby użyć tego separatora. (Jest nawet przeciążenie, które akceptuje całość Stringjako separator).

Pominąłem to w powyższym przykładzie, ale jeśli nie masz pewności, skąd Stringpochodzi lub co może zawierać, możesz sprawdzić, czy lastIndexOfzwraca wartość nieujemną, ponieważ Javadoc twierdzi , że zwróci

-1, jeśli nie ma takiego zdarzenia

Sotirios Delimanolis
źródło
25

Od 1.7

    Path p = Paths.get("c:\\temp\\1.txt");
    String fileName = p.getFileName().toString();
    String directory = p.getParent().toString();
max3d
źródło
11

możesz użyć ścieżki = C: \ Hello \ AnotherFolder \ TheFileName.PDF

String strPath = path.substring(path.lastIndexOf("\\")+1, path.length());
Rakesh
źródło
Powinieneś użyć \\ zamiast \
Anoop Chandrika HarisudhanNair
2
Nie należy używać żadnego z nich, ponieważ jest to zależne od platformy. /na Unix i \`(AND THERE IS A BUG IN THE MARKDOWN PARSER HERE) on windows. You can't know. Use another solution like File` lub Paths.
Automatico
3
Czy File.separatorzależy również od platformy? A może to zadziała ... String strPath = path.substring(path.lastIndexOf(File.separator)+1, path.length());
Jonathan
File.separator i File.separatorChar są zarówno „/” w wersji JDK dla UNIX / Linux / macOS, jak i „\” w wersji dla Windows.
可 可 Jacky
2
File.separatornie zawsze tu będzie działać, ponieważ w systemie Windows nazwę pliku można oddzielić jednym "/"lub "\\".
DodgyCodeException
10

Inne odpowiedzi nie do końca działały w moim konkretnym scenariuszu, w którym czytam ścieżki pochodzące z innego systemu operacyjnego niż mój obecny. Aby rozwinąć, zapisuję załączniki wiadomości e-mail zapisane z platformy Windows na serwerze Linux. Nazwa pliku zwrócona z JavaMail API to coś w rodzaju „C: \ temp \ hello.xls”

Rozwiązanie, z którym skończyłem:

String filenameWithPath = "C:\\temp\\hello.xls";
String[] tokens = filenameWithPath.split("[\\\\|/]");
String filename = tokens[tokens.length - 1];
javaPhobic
źródło
3

Rozważ przypadek, w którym Java jest wieloplatformowa:

int lastPath = fileName.lastIndexOf(File.separator);
if (lastPath!=-1){
    fileName = fileName.substring(lastPath+1);
}
Alejandro Hdz
źródło
1

Metoda bez uzależnienia i dba o .. , . i zduplikowane separatory.

public static String getFileName(String filePath) {
    if( filePath==null || filePath.length()==0 )
        return "";
    filePath = filePath.replaceAll("[/\\\\]+", "/");
    int len = filePath.length(),
        upCount = 0;
    while( len>0 ) {
        //remove trailing separator
        if( filePath.charAt(len-1)=='/' ) {
            len--;
            if( len==0 )
                return "";
        }
        int lastInd = filePath.lastIndexOf('/', len-1);
        String fileName = filePath.substring(lastInd+1, len);
        if( fileName.equals(".") ) {
            len--;
        }
        else if( fileName.equals("..") ) {
            len -= 2;
            upCount++;
        }
        else {
            if( upCount==0 )
                return fileName;
            upCount--;
            len -= fileName.length();
        }
    }
    return "";
}

Przypadek testowy:

@Test
public void testGetFileName() {
    assertEquals("", getFileName("/"));
    assertEquals("", getFileName("////"));
    assertEquals("", getFileName("//C//.//../"));
    assertEquals("", getFileName("C//.//../"));
    assertEquals("C", getFileName("C"));
    assertEquals("C", getFileName("/C"));
    assertEquals("C", getFileName("/C/"));
    assertEquals("C", getFileName("//C//"));
    assertEquals("C", getFileName("/A/B/C/"));
    assertEquals("C", getFileName("/A/B/C"));
    assertEquals("C", getFileName("/C/./B/../"));
    assertEquals("C", getFileName("//C//./B//..///"));
    assertEquals("user", getFileName("/user/java/.."));
    assertEquals("C:", getFileName("C:"));
    assertEquals("C:", getFileName("/C:"));
    assertEquals("java", getFileName("C:\\Program Files (x86)\\java\\bin\\.."));
    assertEquals("C.ext", getFileName("/A/B/C.ext"));
    assertEquals("C.ext", getFileName("C.ext"));
}

Może getFileName jest nieco mylące, ponieważ zwraca także nazwy katalogów. Zwraca nazwę pliku lub ostatniego katalogu w ścieżce.

Yavuzkavus
źródło
0

wypakuj nazwę pliku za pomocą wyrażenia java *.

public String extractFileName(String fullPathFile){
        try {
            Pattern regex = Pattern.compile("([^\\\\/:*?\"<>|\r\n]+$)");
            Matcher regexMatcher = regex.matcher(fullPathFile);
            if (regexMatcher.find()){
                return regexMatcher.group(1);
            }
        } catch (PatternSyntaxException ex) {
            LOG.info("extractFileName::pattern problem <"+fullPathFile+">",ex);
        }
        return fullPathFile;
    }
HJK
źródło
0

Możesz użyć obiektu FileInfo, aby uzyskać wszystkie informacje o swoim pliku.

    FileInfo f = new FileInfo(@"C:\Hello\AnotherFolder\The File Name.PDF");
    MessageBox.Show(f.Name);
    MessageBox.Show(f.FullName);
    MessageBox.Show(f.Extension );
    MessageBox.Show(f.DirectoryName);
Blue Phoenix
źródło