Uzyskaj nazwę pliku z adresu URL


146

W Javie, biorąc pod uwagę a java.net.URLlub a Stringw postaci http://www.example.com/some/path/to/a/file.xml, jaki jest najłatwiejszy sposób uzyskania nazwy pliku bez rozszerzenia? Więc w tym przykładzie szukam czegoś, co zwraca "file".

Potrafię wymyślić kilka sposobów, aby to zrobić, ale szukam czegoś, co jest łatwe do odczytania i krótkie.


3
Zdajesz sobie sprawę, że nie ma wymagania, aby na końcu znajdowała się nazwa pliku, ani nawet coś, co wygląda jak nazwa pliku. W takim przypadku na serwerze może znajdować się plik file.xml lub nie.
Nędzna zmienna

2
w takim przypadku wynikiem byłby pusty ciąg lub może być pusty.
Sietse

1
Myślę, że musisz jaśniej zdefiniować problem. A co z następującymi zakończeniami adresów URL? .... / abc, .... / abc /, .... / abc.def, .... / abc.def.ghi, .... / abc? def.ghi
zmienna

2
Myślę, że to całkiem jasne. Jeśli adres URL wskazuje na plik, interesuje mnie nazwa pliku bez rozszerzenia (jeśli je ma). Części zapytania wykraczają poza nazwę pliku.
Sietse

4
nazwa pliku to część adresu URL po ostatnim ukośniku. rozszerzenie pliku to część nazwy pliku po ostatniej kropce.
Sietse

Odpowiedzi:


189

Zamiast wymyślać koło na nowo, co powiesz na użycie Apache commons-io :

import org.apache.commons.io.FilenameUtils;

public class FilenameUtilTest {

    public static void main(String[] args) throws Exception {
        URL url = new URL("http://www.example.com/some/path/to/a/file.xml?foo=bar#test");

        System.out.println(FilenameUtils.getBaseName(url.getPath())); // -> file
        System.out.println(FilenameUtils.getExtension(url.getPath())); // -> xml
        System.out.println(FilenameUtils.getName(url.getPath())); // -> file.xml
    }

}

2
W wersji commons-io 2.2 przynajmniej nadal musisz ręcznie obsługiwać adresy URL z parametrami. Np " example.com/file.xml?date=2010-10-20 "
Luke Quinane

18
FilenameUtils.getName (url) jest lepszym rozwiązaniem.
ehsun7b

4
Wydaje się dziwne, aby dodać zależność od commons-io, gdy łatwe rozwiązania są łatwo dostępne za pomocą JDK (zobacz URL#getPathi String#substringlub Path#getFileNamelub File#getName).
Jason C

5
Klasa FilenameUtils jest przeznaczona do pracy z systemem Windows i ścieżką * nix, a nie adresem URL.
nhahtdh

4
Zaktualizowany przykład użycia adresu URL, pokazania przykładowych wartości wyjściowych i użycia parametrów zapytania.
Nick Grealy

192
String fileName = url.substring( url.lastIndexOf('/')+1, url.length() );

String fileNameWithoutExtn = fileName.substring(0, fileName.lastIndexOf('.'));

17
Dlaczego głos przeciw? To niesprawiedliwe. Mój kod działa, właśnie zweryfikowałem swój kod po obejrzeniu głosów przeciw.
Real Red.

2
Głosowałem za tobą, ponieważ jest nieco bardziej czytelny niż moja wersja. Głos negatywny może wynikać z tego, że nie działa, gdy nie ma rozszerzenia lub pliku.
Sietse

1
Możesz zostawić drugi parametr nasubstring()
Jon Onstott

12
To nie działa ani dla http://example.org/file#anchor, http://example.org/file?p=foo&q=baranihttp://example.org/file.xml#/p=foo&q=bar
Matthias Ronge

2
Jeśli pozwolisz String url = new URL(original_url).getPath()i dodasz specjalny przypadek dla nazw plików, które nie zawierają .znaku, to działa dobrze.
Jason C

32

Jeśli nie musisz pozbywać się rozszerzenia pliku, oto sposób na zrobienie tego bez uciekania się do podatnej na błędy manipulacji ciągami znaków i bez korzystania z zewnętrznych bibliotek. Działa z Javą 1.7+:

import java.net.URI
import java.nio.file.Paths

String url = "http://example.org/file?p=foo&q=bar"
String filename = Paths.get(new URI(url).getPath()).getFileName().toString()

1
@Carcigenicate Właśnie przetestowałem to ponownie i wydaje się, że działa dobrze. URI.getPath()zwraca a String, więc nie rozumiem, dlaczego to nie zadziała
Zoltán

1
Nvm. Zdaję sobie teraz sprawę, że mój problem wynikał z tego, jak Clojure obsługuje zmienne argumenty podczas współpracy z Javą. Przeciążenie String nie działało, ponieważ konieczne było przekazanie pustej tablicy, aby obsłużyć zmienne argumenty Paths / get. Nadal jednak działa, jeśli pozbędziesz się wywołania getPathi zamiast tego użyjesz przeciążenia URI.
Carcigenicate

@Carcigenicate masz na myśli Paths.get(new URI(url))? To wydaje się nie działać dla mnie
Zoltán

getFileName wymaga interfejsu Android API na poziomie 26
Manuela,

26

Powinno to zmniejszyć (pozostawię ci obsługę błędów):

int slashIndex = url.lastIndexOf('/');
int dotIndex = url.lastIndexOf('.', slashIndex);
String filenameWithoutExtension;
if (dotIndex == -1) {
  filenameWithoutExtension = url.substring(slashIndex + 1);
} else {
  filenameWithoutExtension = url.substring(slashIndex + 1, dotIndex);
}

1
Jeden aspekt obsługi błędów trzeba wziąć pod uwagę to będzie w końcu z pustym ciągiem jeśli przypadkowo przekazać mu adres URL, który nie robi mieć nazwę pliku (na przykład http://www.example.com/lub http://www.example.com/folder/)
rtpHarry

2
Kod nie działa. lastIndexOfnie działa w ten sposób. Ale zamiar jest jasny.
Robert

Ocena negatywna, ponieważ nie zadziała, jeśli fragment zawiera ukośniki i ponieważ istnieją dedykowane funkcje, które osiągają to w apache commons i w Javie od 1.7
Zoltán

14
public static String getFileName(URL extUrl) {
        //URL: "http://photosaaaaa.net/photos-ak-snc1/v315/224/13/659629384/s659629384_752969_4472.jpg"
        String filename = "";
        //PATH: /photos-ak-snc1/v315/224/13/659629384/s659629384_752969_4472.jpg
        String path = extUrl.getPath();
        //Checks for both forward and/or backslash 
        //NOTE:**While backslashes are not supported in URL's 
        //most browsers will autoreplace them with forward slashes
        //So technically if you're parsing an html page you could run into 
        //a backslash , so i'm accounting for them here;
        String[] pathContents = path.split("[\\\\/]");
        if(pathContents != null){
            int pathContentsLength = pathContents.length;
            System.out.println("Path Contents Length: " + pathContentsLength);
            for (int i = 0; i < pathContents.length; i++) {
                System.out.println("Path " + i + ": " + pathContents[i]);
            }
            //lastPart: s659629384_752969_4472.jpg
            String lastPart = pathContents[pathContentsLength-1];
            String[] lastPartContents = lastPart.split("\\.");
            if(lastPartContents != null && lastPartContents.length > 1){
                int lastPartContentLength = lastPartContents.length;
                System.out.println("Last Part Length: " + lastPartContentLength);
                //filenames can contain . , so we assume everything before
                //the last . is the name, everything after the last . is the 
                //extension
                String name = "";
                for (int i = 0; i < lastPartContentLength; i++) {
                    System.out.println("Last Part " + i + ": "+ lastPartContents[i]);
                    if(i < (lastPartContents.length -1)){
                        name += lastPartContents[i] ;
                        if(i < (lastPartContentLength -2)){
                            name += ".";
                        }
                    }
                }
                String extension = lastPartContents[lastPartContentLength -1];
                filename = name + "." +extension;
                System.out.println("Name: " + name);
                System.out.println("Extension: " + extension);
                System.out.println("Filename: " + filename);
            }
        }
        return filename;
    }

13

Jedna wkładka:

new File(uri.getPath).getName

Kompletny kod (w skali REPL):

import java.io.File
import java.net.URI

val uri = new URI("http://example.org/file.txt?whatever")

new File(uri.getPath).getName
res18: String = file.txt

Uwaga : URI#gePathjest wystarczająco inteligentny, aby usunąć parametry zapytania i schemat protokołu. Przykłady:

new URI("http://example.org/hey/file.txt?whatever").getPath
res20: String = /hey/file.txt

new URI("hdfs:///hey/file.txt").getPath
res21: String = /hey/file.txt

new URI("file:///hey/file.txt").getPath
res22: String = /hey/file.txt

1
fajne rozwiązanie!
CybeX

1
jest to najlepsza opcja, ponieważ używa tylko standardowego JDK
Alexandros

11

Uzyskaj nazwę pliku z rozszerzeniem , bez rozszerzenia , tylko rozszerzenie z tylko 3 liniami:

String urlStr = "http://www.example.com/yourpath/foler/test.png";

String fileName = urlStr.substring(urlStr.lastIndexOf('/')+1, urlStr.length());
String fileNameWithoutExtension = fileName.substring(0, fileName.lastIndexOf('.'));
String fileExtension = urlStr.substring(urlStr.lastIndexOf("."));

Log.i("File Name", fileName);
Log.i("File Name Without Extension", fileNameWithoutExtension);
Log.i("File Extension", fileExtension);

Wynik dziennika:

File Name(13656): test.png
File Name Without Extension(13656): test
File Extension(13656): .png

Mam nadzieję, że to ci pomoże.


9

Wymyśliłem to:

String url = "http://www.example.com/some/path/to/a/file.xml";
String file = url.substring(url.lastIndexOf('/')+1, url.lastIndexOf('.'));

Lub w przypadku adresów URL bez pliku, tylko ścieżka.
Sietse

twój kod też jest poprawny. i tak nie powinniśmy sprawdzać negatywnych warunków. głos za ciebie. przy okazji, czy nazwa Dirk Kuyt brzmi znajomo?
Real Red.

8

Jest kilka sposobów:

We / wy plików Java 7:

String fileName = Paths.get(strUrl).getFileName().toString();

Apache Commons:

String fileName = FilenameUtils.getName(strUrl);

Korzystanie z Jersey:

UriBuilder buildURI = UriBuilder.fromUri(strUrl);
URI uri = buildURI.build();
String fileName = Paths.get(uri.getPath()).getFileName();

Podciąg:

String fileName = strUrl.substring(strUrl.lastIndexOf('/') + 1);

Niestety, Twoje rozwiązanie we / wy Java 7 File nie działa. Mam wyjątek. Udało mi się to: Paths.get(new URL(strUrl).getFile()).getFileName().toString(); dziękuję za pomysł!
Sergey Nemchinov

7

Nie komplikuj :

/**
 * This function will take an URL as input and return the file name.
 * <p>Examples :</p>
 * <ul>
 * <li>http://example.com/a/b/c/test.txt -> test.txt</li>
 * <li>http://example.com/ -> an empty string </li>
 * <li>http://example.com/test.txt?param=value -> test.txt</li>
 * <li>http://example.com/test.txt#anchor -> test.txt</li>
 * </ul>
 * 
 * @param url The input URL
 * @return The URL file name
 */
public static String getFileNameFromUrl(URL url) {

    String urlString = url.getFile();

    return urlString.substring(urlString.lastIndexOf('/') + 1).split("\\?")[0].split("#")[0];
}

1
@AlexNauda Wymień url.getFile()z url.toString()i działa ze #w ścieżce.
Sormuras


5

Oto najprostszy sposób na zrobienie tego w systemie Android. Wiem, że to nie zadziała w Javie, ale może pomóc programistom aplikacji na Androida.

import android.webkit.URLUtil;

public String getFileNameFromURL(String url) {
    String fileNameWithExtension = null;
    String fileNameWithoutExtension = null;
    if (URLUtil.isValidUrl(url)) {
        fileNameWithExtension = URLUtil.guessFileName(url, null, null);
        if (fileNameWithExtension != null && !fileNameWithExtension.isEmpty()) {
            String[] f = fileNameWithExtension.split(".");
            if (f != null & f.length > 1) {
                fileNameWithoutExtension = f[0];
            }
        }
    }
    return fileNameWithoutExtension;
}

3

Utwórz obiekt adresu URL z metody String. Kiedy po raz pierwszy masz obiekt URL, istnieją metody umożliwiające łatwe pobranie dowolnego fragmentu informacji, których potrzebujesz.

Mogę zdecydowanie polecić witrynę internetową Javaalmanac, która ma mnóstwo przykładów, ale która od tego czasu się zmieniła. Może Cię zainteresować http://exampledepot.8waytrips.com/egs/java.io/File2Uri.html :

// Create a file object
File file = new File("filename");

// Convert the file object to a URL
URL url = null;
try {
    // The file need not exist. It is made into an absolute path
    // by prefixing the current working directory
    url = file.toURL();          // file:/d:/almanac1.4/java.io/filename
} catch (MalformedURLException e) {
}

// Convert the URL to a file object
file = new File(url.getFile());  // d:/almanac1.4/java.io/filename

// Read the file contents using the URL
try {
    // Open an input stream
    InputStream is = url.openStream();

    // Read from is

    is.close();
} catch (IOException e) {
    // Could not open the file
}

2

Jeśli chcesz uzyskać tylko nazwę pliku z java.net.URL (bez parametrów zapytania), możesz użyć następującej funkcji:

public static String getFilenameFromURL(URL url) {
    return new File(url.getPath().toString()).getName();
}

Na przykład ten wejściowy adres URL:

"http://example.com/image.png?version=2&amp;modificationDate=1449846324000"

Zostanie przetłumaczone na następujący ciąg wyjściowy:

image.png

2

Odkryłem, że niektóre adresy URL są przekazywane bezpośrednio, aby FilenameUtils.getNamezwrócić niechciane wyniki i należy to opakować, aby uniknąć exploitów.

Na przykład,

System.out.println(FilenameUtils.getName("http://www.google.com/.."));

zwroty

..

na które wątpię, by ktokolwiek chciał na to pozwolić

Następująca funkcja wydaje się działać dobrze i pokazuje niektóre z tych przypadków testowych i zwraca, nullgdy nie można określić nazwy pliku.

public static String getFilenameFromUrl(String url)
{
    if (url == null)
        return null;
    
    try
    {
        // Add a protocol if none found
        if (! url.contains("//"))
            url = "http://" + url;

        URL uri = new URL(url);
        String result = FilenameUtils.getName(uri.getPath());

        if (result == null || result.isEmpty())
            return null;

        if (result.contains(".."))
            return null;

        return result;
    }
    catch (MalformedURLException e)
    {
        return null;
    }
}

Całość kończy się kilkoma prostymi przypadkami testowymi w poniższym przykładzie:

import java.util.Objects;
import java.net.URL;
import org.apache.commons.io.FilenameUtils;

class Main {

  public static void main(String[] args) {
    validateFilename(null, null);
    validateFilename("", null);
    validateFilename("www.google.com/../me/you?trex=5#sdf", "you");
    validateFilename("www.google.com/../me/you?trex=5 is the num#sdf", "you");
    validateFilename("http://www.google.com/test.png?test", "test.png");
    validateFilename("http://www.google.com", null);
    validateFilename("http://www.google.com#test", null);
    validateFilename("http://www.google.com////", null);
    validateFilename("www.google.com/..", null);
    validateFilename("http://www.google.com/..", null);
    validateFilename("http://www.google.com/test", "test");
    validateFilename("https://www.google.com/../../test.png", "test.png");
    validateFilename("file://www.google.com/test.png", "test.png");
    validateFilename("file://www.google.com/../me/you?trex=5", "you");
    validateFilename("file://www.google.com/../me/you?trex", "you");
  }

  private static void validateFilename(String url, String expectedFilename){
    String actualFilename = getFilenameFromUrl(url);

    System.out.println("");
    System.out.println("url:" + url);
    System.out.println("filename:" + expectedFilename);

    if (! Objects.equals(actualFilename, expectedFilename))
      throw new RuntimeException("Problem, actual=" + actualFilename + " and expected=" + expectedFilename + " are not equal");
  }

  public static String getFilenameFromUrl(String url)
  {
    if (url == null)
      return null;

    try
    {
      // Add a protocol if none found
      if (! url.contains("//"))
        url = "http://" + url;

      URL uri = new URL(url);
      String result = FilenameUtils.getName(uri.getPath());

      if (result == null || result.isEmpty())
        return null;

      if (result.contains(".."))
        return null;

      return result;
    }
    catch (MalformedURLException e)
    {
      return null;
    }
  }
}

1

Adresy URL mogą mieć na końcu parametry

 /**
 * Getting file name from url without extension
 * @param url string
 * @return file name
 */
public static String getFileName(String url) {
    String fileName;
    int slashIndex = url.lastIndexOf("/");
    int qIndex = url.lastIndexOf("?");
    if (qIndex > slashIndex) {//if has parameters
        fileName = url.substring(slashIndex + 1, qIndex);
    } else {
        fileName = url.substring(slashIndex + 1);
    }
    if (fileName.contains(".")) {
        fileName = fileName.substring(0, fileName.lastIndexOf("."));
    }

    return fileName;
}

/może pojawić się we fragmentach. Wydobędziesz niewłaściwe rzeczy.
nhahtdh

1

UrlObiekt w urllib umożliwia dostęp Niecytowany pliku ścieżka jest. Oto kilka przykładów:

String raw = "http://www.example.com/some/path/to/a/file.xml";
assertEquals("file.xml", Url.parse(raw).path().filename());

raw = "http://www.example.com/files/r%C3%A9sum%C3%A9.pdf";
assertEquals("résumé.pdf", Url.parse(raw).path().filename());

0

odpowiedź Andy'ego została powtórzona za pomocą split ():

Url u= ...;
String[] pathparts= u.getPath().split("\\/");
String filename= pathparts[pathparts.length-1].split("\\.", 1)[0];

0
public String getFileNameWithoutExtension(URL url) {
    String path = url.getPath();

    if (StringUtils.isBlank(path)) {
        return null;
    }
    if (StringUtils.endsWith(path, "/")) {
        //is a directory ..
        return null;
    }

    File file = new File(url.getPath());
    String fileNameWithExt = file.getName();

    int sepPosition = fileNameWithExt.lastIndexOf(".");
    String fileNameWithOutExt = null;
    if (sepPosition >= 0) {
        fileNameWithOutExt = fileNameWithExt.substring(0,sepPosition);
    }else{
        fileNameWithOutExt = fileNameWithExt;
    }

    return fileNameWithOutExt;
}

0

Co powiesz na to:

String filenameWithoutExtension = null;
String fullname = new File(
    new URI("http://www.xyz.com/some/deep/path/to/abc.png").getPath()).getName();

int lastIndexOfDot = fullname.lastIndexOf('.');
filenameWithoutExtension = fullname.substring(0, 
    lastIndexOfDot == -1 ? fullname.length() : lastIndexOfDot);

0

Aby zwrócić nazwę pliku bez rozszerzenia i bez parametrów, użyj:

String filenameWithParams = FilenameUtils.getBaseName(urlStr); // may hold params if http://example.com/a?param=yes
return filenameWithParams.split("\\?")[0]; // removing parameters from url if they exist

Aby zwrócić nazwę pliku z rozszerzeniem bez parametrów, użyj tego:

/** Parses a URL and extracts the filename from it or returns an empty string (if filename is non existent in the url) <br/>
 * This method will work in win/unix formats, will work with mixed case of slashes (forward and backward) <br/>
 * This method will remove parameters after the extension
 *
 * @param urlStr original url string from which we will extract the filename
 * @return filename from the url if it exists, or an empty string in all other cases */
private String getFileNameFromUrl(String urlStr) {
    String baseName = FilenameUtils.getBaseName(urlStr);
    String extension = FilenameUtils.getExtension(urlStr);

    try {
        extension = extension.split("\\?")[0]; // removing parameters from url if they exist
        return baseName.isEmpty() ? "" : baseName + "." + extension;
    } catch (NullPointerException npe) {
        return "";
    }
}

0

Poza wszystkimi zaawansowanymi metodami moja prosta sztuczka to StringTokenizer:

import java.util.ArrayList;
import java.util.StringTokenizer;

public class URLName {
    public static void main(String args[]){
        String url = "http://www.example.com/some/path/to/a/file.xml";
        StringTokenizer tokens = new StringTokenizer(url, "/");

        ArrayList<String> parts = new ArrayList<>();

        while(tokens.hasMoreTokens()){
            parts.add(tokens.nextToken());
        }
        String file = parts.get(parts.size() -1);
        int dot = file.indexOf(".");
        String fileName = file.substring(0, dot);
        System.out.println(fileName);
    }
}

0

Jeśli używasz Springa , istnieje pomocnik do obsługi identyfikatorów URI. Oto rozwiązanie:

List<String> pathSegments = UriComponentsBuilder.fromUriString(url).build().getPathSegments();
String filename = pathSegments.get(pathSegments.size()-1);


-1
create a new file with string image path

    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

Mam ten sam problem z twoim. Rozwiązałem to w ten sposób:

var URL = window.location.pathname; // Gets page name
var page = URL.substring(URL.lastIndexOf('/') + 1); 
console.info(page)

Java to nie JavaScript
nathanfranke

-3

import java.io. *;

import java.net.*;

public class ConvertURLToFileName{


   public static void main(String[] args)throws IOException{
   BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
   System.out.print("Please enter the URL : ");

   String str = in.readLine();


   try{

     URL url = new URL(str);

     System.out.println("File : "+ url.getFile());
     System.out.println("Converting process Successfully");

   }  
   catch (MalformedURLException me){

      System.out.println("Converting process error");

 }

Mam nadzieję, że to Ci pomoże.


2
getFile () nie robi tego, co myślisz. Zgodnie z dokumentem jest to getPath () + getQuery, co jest raczej bezcelowe. java.sun.com/j2se/1.4.2/docs/api/java/net/URL.html#getFile ()
bobince
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.