Ottieni il nome del file dall'URL


146

In Java, dato un java.net.URLo un Stringin forma di http://www.example.com/some/path/to/a/file.xml, qual è il modo più semplice per ottenere il nome del file, meno l'estensione? Quindi, in questo esempio, sto cercando qualcosa che ritorni "file".

Posso pensare a diversi modi per farlo, ma sto cercando qualcosa che sia facile da leggere e breve.


3
Ti rendi conto che non è necessario che ci sia un nome file alla fine, o anche qualcosa che assomigli a un nome file. In questo caso, potrebbe esserci o meno un file.xml sul server.
Miserabile variabile

2
in tal caso, il risultato sarebbe una stringa vuota o forse nulla.
Sietse

1
Penso che sia necessario definire il problema in modo più chiaro. Che dire delle seguenti terminazioni URL? .... / abc, .... / abc /, .... / abc.def, .... / abc.def.ghi, .... / abc? def.ghi
Miserabile variabile

2
Penso che sia abbastanza chiaro. Se l'URL punta a un file, mi interessa il nome del file meno l'estensione (se ne ha uno). Le parti di query non rientrano nel nome file.
Sietse

4
il nome del file è la parte dell'URL dopo l'ultima barra. l'estensione del file è la parte del nome del file dopo l'ultimo periodo.
Sietse,

Risposte:


189

Invece di reinventare la ruota, che ne dici di usare 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
Nella versione commons-io 2.2 almeno devi ancora gestire manualmente gli URL con parametri. Ad esempio " esempio.com/file.xml?date=2010-10-20 "
Luke Quinane

18
FilenameUtils.getName (url) si adatta meglio.
ehsun7b,

4
Sembra strano aggiungere una dipendenza da commons-io quando le soluzioni facili sono prontamente disponibili semplicemente usando JDK (vedi URL#getPathe String#substringo Path#getFileNameo File#getName).
Jason C,

5
La classe FilenameUtils è progettata per funzionare con il percorso Windows e * nix, non con l'URL.
nhahtdh,

4
Esempio aggiornato per utilizzare un URL, mostrare i valori di output di esempio e utilizzare i parametri di query.
Nick Grealy,

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

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

17
Perché il downvote? Questo è ingiusto. Il mio codice funziona, ho appena verificato il mio codice dopo aver visto il downvote.
Rosso reale.

2
Ti ho votato perché è leggermente più leggibile della mia versione. Il downvote potrebbe essere dovuto al fatto che non funziona in assenza di estensione o file.
Sietse

1
Puoi lasciare il secondo parametro asubstring()
Jon Onstott il

12
Questo non funziona per nessuno dei due http://example.org/file#anchor, http://example.org/file?p=foo&q=barhttp://example.org/file.xml#/p=foo&q=bar
Matthias Ronge

2
Se lasci String url = new URL(original_url).getPath()e aggiungi un caso speciale per i nomi di file che non contengono un, .allora funziona bene.
Jason C,

32

Se non è necessario eliminare l'estensione del file, ecco un modo per farlo senza ricorrere alla manipolazione di stringhe soggetta a errori e senza utilizzare librerie esterne. Funziona con 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
@Carcigenicato L'ho appena provato di nuovo e sembra funzionare bene. URI.getPath()restituisce un String, quindi non vedo perché non funzionerebbe
Zoltán

1
NVM. Ora mi rendo conto che il mio problema era dovuto al modo in cui Clojure gestisce var-args durante l'interoperabilità Java. Il sovraccarico della stringa non funzionava perché doveva essere passato anche un array vuoto per gestire i var-arg di Paths / get. Funziona comunque se ti sbarazzi della chiamata getPathe usi invece il sovraccarico URI.
Carcigenicate,

@Carcigenicato intendi Paths.get(new URI(url))? Non sembra funzionare per me
Zoltán l'

getFileName richiede android api livello 26
Manuela

26

Questo dovrebbe tagliarlo (lascio a te la gestione degli errori):

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
Un aspetto della gestione degli errori che devi considerare è che http://www.example.com/http://www.example.com/folder/
finirai

2
Il codice non funziona. lastIndexOfnon funziona in questo modo. Ma l'intenzione è chiara.
Robert,

Sottovalutato perché non funzionerà se la parte del frammento contiene barre, e perché ci sono funzioni dedicate che lo ottengono nei comuni apache e in Java dall'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

Una fodera:

new File(uri.getPath).getName

Codice completo (in una 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

Nota : URI#gePathè già abbastanza intelligente da eliminare i parametri della query e lo schema del protocollo. Esempi:

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
bella soluzione!
CybeX,

1
questa è l'opzione migliore, in quanto utilizza solo JDK standard
Alexandros,

11

Ottieni nome file con estensione , senza estensione , solo estensione con solo 3 righe:

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

Risultato del registro:

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

Spero che ti possa aiutare.


9

Ho pensato a questo:

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

O su URL senza file, solo un percorso.
Sietse

anche il tuo codice è corretto. non dovremmo comunque verificare condizioni negative. un voto per te. a proposito il nome dirk kuyt suona familiare?
Rosso reale.

8

Ci sono alcuni modi:

I / O file Java 7:

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

Apache Commons:

String fileName = FilenameUtils.getName(strUrl);

Utilizzando Jersey:

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

substring:

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

Sfortunatamente, la tua soluzione I / O per file Java 7 non funziona per me. Ho ricevuto un'eccezione. Ci riesco: Paths.get(new URL(strUrl).getFile()).getFileName().toString(); grazie per l'idea!
Sergey Nemchinov,

7

Mantienilo semplice:

/**
 * 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 Sostituisci url.getFile()con url.toString()e funziona con #nel percorso.
Sormuras,


5

Ecco il modo più semplice per farlo in Android. So che non funzionerà in Java ma può aiutare lo sviluppatore di applicazioni Android.

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

Crea un oggetto URL dalla stringa. Quando hai per la prima volta un oggetto URL, ci sono metodi per estrarre facilmente qualsiasi frammento di informazioni di cui hai bisogno.

Consiglio vivamente il sito Web Javaalmanac che contiene molti esempi, ma che da allora si è spostato. Potresti trovare interessante 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

Se si desidera ottenere solo il nome file da un file java.net.URL (esclusi i parametri di query), è possibile utilizzare la seguente funzione:

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

Ad esempio, questo URL di input:

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

Sarebbe tradotto in questa stringa di output:

image.png

2

Ho scoperto che alcuni URL quando vengono passati direttamente per FilenameUtils.getNamerestituire risultati indesiderati e questo deve essere concluso per evitare exploit.

Per esempio,

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

ritorna

..

che dubito che chiunque voglia permettere.

La seguente funzione sembra funzionare correttamente e mostra alcuni di questi casi di test e ritorna nullquando non è possibile determinare il nome file.

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

Questo è racchiuso in alcuni semplici casi di test nel seguente esempio:

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

Gli URL alla fine possono avere parametri, questo

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

/può apparire in frammento. Estrai le cose sbagliate.
nhahtdh,

1

L' Urloggetto in urllib ti consente di accedere al nome file senza escape del percorso. Ecco alcuni esempi:

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

la risposta di Andy è stata rifatta usando 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

Cosa ne pensi di questo:

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

Per restituire il nome file senza estensione e senza parametri utilizzare quanto segue:

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

Per restituire il nome file con estensione senza parametri utilizzare questo:

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

Al di là di tutti i metodi avanzati, il mio semplice trucco è 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

Se stai usando Spring , c'è un aiutante per gestire gli URI. Ecco la soluzione:

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

Ho lo stesso problema, con il tuo. L'ho risolto con questo:

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

Java non è JavaScript
nathanfranke il

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

 }

Spero che questo ti possa aiutare.


2
getFile () non fa ciò che pensi. Secondo il documento in realtà è getPath () + getQuery, che è piuttosto inutile. java.sun.com/j2se/1.4.2/docs/api/java/net/URL.html#getFile ()
bobince
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.