Nhận tên tệp từ URL


146

Trong Java, được cung cấp một java.net.URLhoặc một Stringdạng http://www.example.com/some/path/to/a/file.xml, cách dễ nhất để có được tên tệp, trừ phần mở rộng là gì? Vì vậy, trong ví dụ này, tôi đang tìm kiếm thứ gì đó trả về "file".

Tôi có thể nghĩ ra một số cách để làm điều này, nhưng tôi đang tìm kiếm thứ gì đó dễ đọc và ngắn gọn.


3
BẠN nhận ra rằng không có yêu cầu phải có một tên tệp ở cuối, hoặc thậm chí một cái gì đó trông giống như một tên tệp. Trong trường hợp này, có thể có hoặc không có tệp tin XML trên máy chủ.
Biến thiên khổ sở

2
trong trường hợp đó, kết quả sẽ là một chuỗi rỗng hoặc có thể là null.
Sietse

1
Tôi nghĩ bạn cần xác định vấn đề rõ ràng hơn. Điều gì về các kết thúc URLS sau đây? .... / abc, .... / abc /, .... / abc.def, .... / abc.def.ghi, .... / abc? def.ghi
Biến khổ

2
Tôi nghĩ nó khá rõ ràng. Nếu URL trỏ đến một tệp, tôi quan tâm đến tên tệp trừ phần mở rộng (nếu có). Các phần truy vấn nằm ngoài tên tệp.
Sietse

4
tên tệp là một phần của url sau dấu gạch chéo cuối cùng. phần mở rộng tập tin là một phần của tên tập tin sau khoảng thời gian cuối cùng.
Ngày

Câu trả lời:


188

Thay vì phát minh lại bánh xe, hãy sử dụng 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
Trong phiên bản commons-io 2.2, ít nhất bạn vẫn cần xử lý thủ công các URL với các tham số. Ví dụ: " example.com/file.xml?date=2010-10-20 "
Luke Quinane

18
FilenameUtils.getName (url) phù hợp hơn.
ehsun7b

4
Nó có vẻ kỳ lạ để thêm một sự phụ thuộc vào commons-io khi giải pháp dễ dàng là có sẵn chỉ bằng cách sử dụng JDK (xem URL#getPathString#substringhay Path#getFileNamehay File#getName).
Jason C

5
Lớp FilenameUtils được thiết kế để hoạt động với đường dẫn Windows và * nix, không phải URL.
nhahtdh

4
Ví dụ được cập nhật để sử dụng URL, hiển thị giá trị đầu ra mẫu và sử dụng tham số truy vấn.
Nick Grealy

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

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

17
Tại sao các downvote? Điều này không công bằng. Mã của tôi hoạt động, tôi chỉ cần xác minh mã của mình sau khi thấy downvote.
Màu đỏ thật.

2
Tôi đánh giá cao bạn, bởi vì nó dễ đọc hơn phiên bản của tôi một chút. Downvote có thể là do nó không hoạt động khi không có phần mở rộng hoặc không có tệp.
Sietse

1
Bạn có thể để lại tham số thứ hai chosubstring()
Jon Onstott

12
Điều này không hoạt động cho cả http://example.org/file#anchor, http://example.org/file?p=foo&q=barcũng khônghttp://example.org/file.xml#/p=foo&q=bar
Matthias Rrid

2
Nếu bạn để String url = new URL(original_url).getPath()và thêm một trường hợp đặc biệt cho tên tệp không chứa .thì nó sẽ hoạt động tốt.
Jason C

32

Nếu bạn không cần phải thoát khỏi phần mở rộng tập tin, đây là một cách để làm điều đó mà không cần dùng đến thao tác Chuỗi dễ bị lỗi và không sử dụng các thư viện bên ngoài. Hoạt động với 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 Tôi mới thử lại lần nữa và nó có vẻ hoạt động tốt. URI.getPath()trả về a String, vì vậy tôi không hiểu tại sao nó không hoạt động
Zoltán

1
Nvm. Bây giờ tôi nhận ra rằng vấn đề của tôi là do cách Clojure xử lý var-args trong quá trình chuyển đổi Java. Quá tải chuỗi không hoạt động vì một mảng trống cũng cần phải được thông qua để xử lý var-args của Paths / get. Nó vẫn hoạt động mặc dù nếu bạn thoát khỏi cuộc gọi đến getPathvà sử dụng quá tải URI thay thế.
Carcigenicate

@Carcigenicate ý bạn là Paths.get(new URI(url))gì? Điều đó dường như không hiệu quả với tôi
Zoltán

getFileName yêu cầu api android cấp 26
Manuela

26

Điều này sẽ về việc cắt nó (tôi sẽ để lại xử lý lỗi cho bạn):

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
Một khía cạnh xử lý lỗi bạn cần xem xét là bạn sẽ kết thúc bằng một chuỗi trống nếu bạn vô tình truyền cho nó một url không có tên tệp (chẳng hạn như http://www.example.com/hoặc http://www.example.com/folder/)
rtpHarry

2
Mã không hoạt động. lastIndexOfkhông hoạt động theo cách này. Nhưng ý định là rõ ràng.
Robert

Bị từ chối vì nó sẽ không hoạt động nếu phần phân đoạn chứa dấu gạch chéo và vì có các hàm chuyên dụng đạt được điều này trong commache commons và trong Java kể từ 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

Lót:

new File(uri.getPath).getName

Mã hoàn chỉnh (trong một REPL scala):

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

Lưu ý : URI#gePathđã đủ thông minh để loại bỏ các tham số truy vấn và sơ đồ của giao thức. Ví dụ:

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
giải pháp tốt đẹp!
CybeX

1
đây là tùy chọn tốt nhất, vì nó chỉ sử dụng JDK tiêu chuẩn
Alexandros

11

Nhận tên tệp có tiện ích mở rộng , không có tiện ích mở rộng , chỉ có tiện ích mở rộng chỉ với 3 dòng:

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

Đăng nhập kết quả:

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

Hy vọng nó sẽ giúp bạn.


9

Tôi đã nghĩ ra điều này:

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

Hoặc trên các URL không có tệp, chỉ là một đường dẫn.
Sietse

mã của bạn là chính xác quá. chúng tôi không phải kiểm tra các điều kiện tiêu cực. một upvote cho bạn. btw tên dirk kuyt nghe có quen không?
Màu đỏ thật.

7

Giữ cho nó đơn giản:

/**
 * 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 Thay thế url.getFile()bằng url.toString()và nó hoạt động với #trong đường dẫn.
Sormuras


7

Có một số cách:

I / O tệp Java 7:

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

Cộng đồng Apache:

String fileName = FilenameUtils.getName(strUrl);

Sử dụng Jersey:

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

Chuỗi con:

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

Thật không may, giải pháp I / O tệp Java 7 của bạn không hoạt động với tôi. Tôi có một ngoại lệ. Tôi thành công với điều này: Paths.get(new URL(strUrl).getFile()).getFileName().toString(); Cảm ơn bạn cho ý tưởng!
Serge Nemchinov

5

Đây là cách đơn giản nhất để làm điều đó trong Android. Tôi biết nó sẽ không hoạt động trong Java nhưng nó có thể giúp nhà phát triển ứng dụng 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

Tạo một đối tượng URL từ Chuỗi. Khi lần đầu tiên bạn có một đối tượng URL, có các phương pháp để dễ dàng lấy ra bất kỳ đoạn thông tin nào bạn cần.

Tôi hoàn toàn có thể giới thiệu trang web Javaalmanac có rất nhiều ví dụ, nhưng nó đã được chuyển đi. Bạn có thể thấy http://examplingepot.8waytrips.com/egs/java.io/File2Uri.html thú vị:

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

Nếu bạn chỉ muốn lấy tên tệp từ java.net.URL (không bao gồm bất kỳ tham số truy vấn nào), bạn có thể sử dụng chức năng sau:

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

Ví dụ: URL đầu vào này:

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

Sẽ được dịch sang chuỗi đầu ra này:

image.png

2

Tôi đã thấy rằng một số url khi được truyền trực tiếp để FilenameUtils.getNametrả về kết quả không mong muốn và điều này cần được gói lại để tránh khai thác.

Ví dụ,

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

trả lại

..

mà tôi nghi ngờ bất cứ ai muốn cho phép.

Hàm sau có vẻ hoạt động tốt và hiển thị một số trường hợp thử nghiệm này và nó sẽ trả về nullkhi tên tệp không thể được xác định.

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

Điều này được gói gọn với một số trường hợp thử nghiệm đơn giản trong ví dụ sau:

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

Các Url có thể có các tham số cuối cùng, điều này

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

/có thể xuất hiện trong đoạn. Bạn sẽ trích xuất những thứ sai.
nhahtdh

1

Đối Urltượng trong urllib cho phép bạn truy cập tên tệp không thoát của đường dẫn. Dưới đây là một số ví dụ:

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

andy trả lời làm lại bằng cách sử dụng 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

Còn cái này thì sao:

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

Để trả về tên tệp không có phần mở rộngkhông có tham số, hãy sử dụng như sau:

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

Để trả về tên tệp có phần mở rộng không có thông số, hãy sử dụng:

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

Ngoài tất cả các phương pháp nâng cao, mẹo đơn giản của tôi là 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

Nếu bạn đang sử dụng Spring , có một trình trợ giúp để xử lý các URI. Đây là giải pháp:

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

Tôi có cùng một vấn đề, với bạn. Tôi đã giải quyết nó bằng cách này:

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

Java không phải là JavaScript
nathanfranke

-3

nhập 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");

 }

Tôi hy vọng điều này sẽ giúp bạn.


2
getFile () không làm những gì bạn nghĩ. Theo tài liệu, nó thực sự là getPath () + getQuery, điều này khá vô nghĩa. java.sun.com/j2se/1.4.2/docs/api/java/net/URL.html#getFile ()
bobince
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.