Dateinamen von URL abrufen


146

Was ist in Java bei einem java.net.URLoder einem Stringin Form von http://www.example.com/some/path/to/a/file.xmlder einfachste Weg, den Dateinamen abzüglich der Erweiterung zu erhalten? In diesem Beispiel suche ich nach etwas, das zurückkehrt "file".

Ich kann mir verschiedene Möglichkeiten vorstellen, dies zu tun, aber ich suche nach etwas, das leicht zu lesen und kurz ist.


3
SIE erkennen, dass am Ende kein Dateiname oder etwas, das wie ein Dateiname aussieht, erforderlich ist. In diesem Fall befindet sich möglicherweise eine file.xml auf dem Server.
Elende Variable

2
In diesem Fall wäre das Ergebnis eine leere Zeichenfolge oder möglicherweise null.
Sietse

1
Ich denke, Sie müssen das Problem klarer definieren. Was ist mit folgenden URLS-Endungen? .... / abc, .... / abc /, .... / abc.def, .... / abc.def.ghi, .... / abc? def.ghi
Variable

2
Ich denke es ist ziemlich klar. Wenn die URL auf eine Datei verweist, interessiert mich der Dateiname abzüglich der Erweiterung (falls vorhanden). Abfrageteile liegen außerhalb des Dateinamens.
Sietse

4
Der Dateiname ist der Teil der URL nach dem letzten Schrägstrich. Die Dateierweiterung ist der Teil des Dateinamens nach dem letzten Zeitraum.
Sietse

Antworten:


188

Anstatt das Rad neu zu erfinden, können Sie Apache commons-io verwenden :

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
Zumindest in Version commons-io 2.2 müssen Sie URLs mit Parametern noch manuell verarbeiten. ZB " example.com/file.xml?date=2010-10-20 "
Luke Quinane

18
DateinameUtils.getName (URL) passt besser.
ehsun7b

4
Es erscheint seltsam, eine Abhängigkeit von Commons-Io hinzuzufügen, wenn einfache Lösungen nur mit dem JDK verfügbar sind (siehe URL#getPathund String#substringoder Path#getFileNameoder File#getName).
Jason C

5
Die FilenameUtils-Klasse funktioniert mit Windows und * nix path, nicht mit URL.
nhahtdh

4
Das Beispiel wurde aktualisiert, um eine URL zu verwenden, Beispielausgabewerte anzuzeigen und Abfrageparameter zu verwenden.
Nick Grealy

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

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

17
Warum das Downvote? Das ist unfair. Mein Code funktioniert, ich habe meinen Code erst überprüft, nachdem ich die Abwertung gesehen habe.
Echtes Rot.

2
Ich habe dich positiv bewertet, weil es etwas lesbarer ist als meine Version. Die Ablehnung kann daran liegen, dass es nicht funktioniert, wenn es keine Erweiterung oder keine Datei gibt.
Sietse

1
Sie können den zweiten Parameter substring()
weglassen

12
Das funktioniert nicht , weder für http://example.org/file#anchor, http://example.org/file?p=foo&q=barnochhttp://example.org/file.xml#/p=foo&q=bar
Matthias Ronge

2
Wenn Sie String url = new URL(original_url).getPath()einen Sonderfall für Dateinamen zulassen und hinzufügen, die kein a enthalten, .funktioniert dies einwandfrei.
Jason C

32

Wenn Sie die Dateierweiterung nicht entfernen müssen, können Sie dies folgendermaßen tun, ohne auf fehleranfällige String-Manipulationen zurückgreifen zu müssen und ohne externe Bibliotheken zu verwenden. Funktioniert mit Java 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 Ich habe es gerade noch einmal getestet und es scheint gut zu funktionieren. URI.getPath()gibt ein zurück String, also verstehe ich nicht, warum es nicht funktionieren würde
Zoltán

1
Nvm. Mir ist jetzt klar, dass mein Problem darauf zurückzuführen ist, wie Clojure während Java-Interop mit var-args umgeht. Die String-Überladung funktionierte nicht, da auch ein leeres Array übergeben werden musste, um die var-args von Paths / get zu verarbeiten. Es funktioniert jedoch immer noch, wenn Sie den Aufruf von loswerden getPathund stattdessen die URI-Überladung verwenden.
Carcigenicate

@Carcigenicate meinst du Paths.get(new URI(url))? Das scheint für mich nicht zu funktionieren
Zoltán

getFileName benötigt Android API Level 26
Manuela

26

Dies sollte ungefähr gekürzt werden (ich überlasse die Fehlerbehandlung Ihnen):

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
Ein Aspekt der Fehlerbehandlung, den Sie berücksichtigen müssen, ist, dass Sie eine leere Zeichenfolge erhalten, wenn Sie versehentlich eine URL übergeben, die keinen Dateinamen (wie http://www.example.com/oder http://www.example.com/folder/) hat
rtpHarry

2
Der Code funktioniert nicht. lastIndexOffunktioniert so nicht. Aber die Absicht ist klar.
Robert

Downvoted, weil es nicht funktioniert, wenn der Fragmentteil Schrägstriche enthält, und weil es dedizierte Funktionen gibt, die dies in Apache Commons und in Java seit 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

Einzeiler:

new File(uri.getPath).getName

Vollständiger Code (in einer Scala 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

Hinweis : URI#gePathIst bereits intelligent genug, um Abfrageparameter und das Protokollschema zu entfernen. Beispiele:

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
schöne Lösung!
CybeX

1
Dies ist die beste Option, da nur Standard-JDK verwendet wird
Alexandros

11

Get Dateinamen mit Extension , ohne Erweiterung , nur Erweiterung mit nur 3 line:

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

Protokoll Ergebnis:

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

Hoffe es wird dir helfen.


9

Ich habe mir Folgendes ausgedacht:

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

Oder auf URLs ohne Datei, nur einen Pfad.
Sietse

Ihr Code ist auch korrekt. Wir sollten sowieso nicht nach negativen Bedingungen suchen. eine positive Bewertung für Sie. Übrigens kommt mir der Name dirk kuyt bekannt vor?
Echtes Rot.

7

Halte es einfach :

/**
 * 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 Ersetzen url.getFile() durch url.toString()und es funktioniert mit #im Pfad.
Sormuras


7

Es gibt einige Möglichkeiten:

Java 7-Datei-E / A:

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

Apache Commons:

String fileName = FilenameUtils.getName(strUrl);

Jersey verwenden:

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

Teilzeichenfolge:

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

Leider funktioniert Ihre Java 7 File I / O- Lösung bei mir nicht. Ich habe eine Ausnahme. Das gelingt mir: Paths.get(new URL(strUrl).getFile()).getFileName().toString(); Danke für die Idee!
Sergey Nemchinov

5

Hier ist der einfachste Weg, dies in Android zu tun. Ich weiß, dass es in Java nicht funktioniert, aber es kann Android-Anwendungsentwicklern helfen.

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

Erstellen Sie ein URL-Objekt aus der Zeichenfolge. Wenn Sie zum ersten Mal ein URL-Objekt haben, gibt es Methoden, mit denen Sie auf einfache Weise nahezu alle benötigten Informationen herausholen können.

Ich kann die Javaalmanac-Website nur empfehlen, die unzählige Beispiele enthält, aber inzwischen umgezogen ist. Vielleicht finden Sie http://exampledepot.8waytrips.com/egs/java.io/File2Uri.html interessant:

// 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

Wenn Sie nur den Dateinamen von einer java.net.URL abrufen möchten (ohne Abfrageparameter), können Sie die folgende Funktion verwenden:

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

Zum Beispiel diese Eingabe-URL:

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

Würde in diese Ausgabe übersetzt String:

image.png

2

Ich habe festgestellt, dass einige URLs direkt an übergeben werden FilenameUtils.getName um unerwünschte Ergebnisse zurückzugeben, und dies muss abgeschlossen werden, um Exploits zu vermeiden.

Beispielsweise,

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

kehrt zurück

..

was ich bezweifle, dass jemand erlauben will.

Die folgende Funktion scheint einwandfrei zu funktionieren und zeigt einige dieser Testfälle. Sie wird zurückgegeben, nullwenn der Dateiname nicht ermittelt werden kann.

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

Dies wird im folgenden Beispiel mit einigen einfachen Testfällen abgeschlossen:

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

Urls können am Ende Parameter haben, dies

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

/kann in Fragment erscheinen. Sie werden das falsche Zeug extrahieren.
nhahtdh

1

Mit dem UrlObjekt in urllib können Sie auf den nicht entkoppelten Dateinamen des Pfads zugreifen. Hier sind einige Beispiele:

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

andys Antwort mit split () wiederholt:

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

Wie wäre es damit:

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

Verwenden Sie Folgendes , um den Dateinamen ohne Erweiterung und ohne Parameter zurückzugeben :

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

Um einen Dateinamen mit einer Erweiterung ohne Parameter zurückzugeben, verwenden Sie Folgendes :

/** 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

Abgesehen von allen fortgeschrittenen Methoden ist mein einfacher Trick 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

Wenn Sie Spring verwenden , gibt es einen Helfer für die Behandlung von URIs. Hier ist die Lösung:

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

Ich habe das gleiche Problem mit deinem. Ich habe es dadurch gelöst:

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

Java ist kein 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");

 }

Ich hoffe, dies wird dir helfen.


2
getFile () macht nicht das, was Sie denken. Laut dem Dokument ist es tatsächlich getPath () + getQuery, was ziemlich sinnlos ist. java.sun.com/j2se/1.4.2/docs/api/java/net/URL.html#getFile ()
Bobince
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.