วิธีรับส่วนเส้นทางสุดท้ายของ URI


114

ฉันมีเป็นอินพุตสตริงที่เป็นไฟล์URI. เป็นไปได้อย่างไรที่จะได้รับส่วนเส้นทางสุดท้าย (ในกรณีของฉันคือ id)

นี่คือ URL ที่ฉันป้อน:

String uri = "http://base_path/some_segment/id"

และฉันต้องได้รับรหัสที่ฉันได้ลองกับสิ่งนี้:

String strId = "http://base_path/some_segment/id";
strId = strId.replace(path);
strId = strId.replaceAll("/", "");
Integer id =  new Integer(strId);
return id.intValue();

แต่มันไม่ได้ผลและต้องมีวิธีที่ดีกว่านี้แน่นอน

คำตอบ:


174

นั่นคือสิ่งที่คุณกำลังมองหา:

URI uri = new URI("http://example.com/foo/bar/42?param=true");
String path = uri.getPath();
String idStr = path.substring(path.lastIndexOf('/') + 1);
int id = Integer.parseInt(idStr);

อีกทางเลือกหนึ่ง

URI uri = new URI("http://example.com/foo/bar/42?param=true");
String[] segments = uri.getPath().split("/");
String idStr = segments[segments.length-1];
int id = Integer.parseInt(idStr);

49
ฉันค้นหา android.net.Uri ของ Android (ไม่ใช่ java.net.URI) และลงเอยที่นี่ หากคุณใช้สิ่งนั้นแทนจะมีวิธีการที่เรียกว่า getLastPathSegment () ซึ่งควรทำในสิ่งเดียวกัน :)
pm_labs

5
เพียงทำเช่นString idStr = new File(uri.getPath()).getName()เดียวกับคำตอบนี้ แต่ใช้FileแทนStringการแยกเส้นทาง
Jason C

เคยชินทำงานนี้สำหรับ URL เช่นexample.com/job/senior-health-and-nutrition-advisor/?param=true ล่าสุด "/" กำลังสร้างปัญหา ต้องการสิ่งที่ดีมากกว่าคำตอบ getLastPathSegment () ที่ให้โดย @paul_sns นั้นสมบูรณ์แบบ
Vaibhav Kadam

@VaibhavKadam ในทางเทคนิคคุณสามารถโต้แย้งได้ว่าส่วนสุดท้ายเป็นสตริงว่าง แต่ถ้านั่นไม่ใช่สิ่งที่คุณต้องการก็ใช้:while (path.endsWith("/")) path = path.substring(0, path.length() - 1);
sfussenegger

@sfussenegger ฉันไม่ดีฉันไม่ได้อ่านแท็กที่มีปัญหา ฉันคิดว่ามันมีแท็กของ android +1 ดีสำหรับ android.net.uri :) Android กำลังเข้าครอบครอง JAVA
Vaibhav Kadam

69
import android.net.Uri;
Uri uri = Uri.parse("http://example.com/foo/bar/42?param=true");
String token = uri.getLastPathSegment();

1
นี่คือ "android.net.Uri" หรือไม่ ฐานอย่าใช้แท็กของคำถาม java.net.URI จะถือว่าและไม่มี getLastPathSegment () ...
Michael Geiser

นอกจากนี้Uriชื่อคลาสAndroid ยังเป็นตัวพิมพ์เล็กและไม่สามารถสร้างอินสแตนซ์ได้ ฉันได้แก้ไขคำตอบของคุณให้ใช้วิธีโรงงานแบบคงที่Uri.parse()แล้ว
quietmint

GetLastPathSegment ไม่มีอยู่ที่นี่
Abdullah Shoaib

2
มันมี getLastPathSegment () แต่ไม่ได้ผล! คืนค่าว่าง!
Junia Montana

ดูเหมือนว่า getLastPathSegment () สุ่มแจกเส้นทางแบบเต็มให้ฉัน
MobDev

48

นี่เป็นวิธีการสั้น ๆ ในการดำเนินการ:

public static String getLastBitFromUrl(final String url){
    // return url.replaceFirst("[^?]*/(.*?)(?:\\?.*)","$1);" <-- incorrect
    return url.replaceFirst(".*/([^/?]+).*", "$1");
}

รหัสทดสอบ:

public static void main(final String[] args){
    System.out.println(getLastBitFromUrl(
        "http://example.com/foo/bar/42?param=true"));
    System.out.println(getLastBitFromUrl("http://example.com/foo"));
    System.out.println(getLastBitFromUrl("http://example.com/bar/"));
}

เอาท์พุท:

42
foo
bar

คำอธิบาย:

.*/      // find anything up to the last / character
([^/?]+) // find (and capture) all following characters up to the next / or ?
         // the + makes sure that at least 1 character is matched
.*       // find all following characters


$1       // this variable references the saved second group from above
         // I.e. the entire string is replaces with just the portion
         // captured by the parentheses above

ในขณะที่ฉันเป็นแฟนตัวยงของ regex และใช้บ่อยครั้งด้วยตัวเองฉันรู้ดีว่าสำหรับนักพัฒนาส่วนใหญ่ regex นั้นค่อนข้างป้านเท่าที่จะทำได้ มันไม่ง่ายไปกว่านี้ในความจริงที่ว่ามันไม่เข้าใจอย่างรวดเร็ว
Bill Turner

/ในตัวละครคลาสเมื่อตะกี้[^/?]ไม่จำเป็นเพราะมันจะไม่เคยถูกจับคู่ .*/จะจับคู่สุดท้าย /ใน String เสมอดังนั้นจึงไม่/ควรพบรายการอื่น
Stefan van den Akker

ใช้ไม่ได้กับลิงก์ประเภทนี้http://example.com/foo#reply2จะเป็นการดีมากหากคุณสามารถอัปเดตคำตอบเพื่อแก้ปัญหาได้ ขอบคุณ
Seth

23

ฉันรู้ว่ามันเก่า แต่การแก้ปัญหาที่นี่ดูเหมือนจะค่อนข้างละเอียด เพียงแค่ซับเดียวที่อ่านได้ง่ายหากคุณมีURLหรือURI:

String filename = new File(url.getPath()).getName();

หรือหากคุณมีString:

String filename = new File(new URL(url).getPath()).getName();

มันทำงานร่วมกับตัวเลือกที่เป็นไปได้ทั้งหมดของ URL เช่นa.co/last?a=1#frag. path.substring(index + 1)ผมคิดว่าไม่เป็นรหัสไม่ย่อยของสัญลักษณ์เส้นทางที่ผ่านมาจนถึงวันสิ้นสุด:
AlikElzin-kilaka

4
@alik คำถามถามถึงส่วนเส้นทางสุดท้าย แบบสอบถามและส่วนย่อยไม่ได้เป็นส่วนหนึ่งของเซ็กเมนต์เส้นทาง
Jason C

13

หากคุณใช้ Java 8 และคุณต้องการส่วนสุดท้ายในเส้นทางไฟล์คุณสามารถทำได้

Path path = Paths.get("example/path/to/file");
String lastSegment = path.getFileName().toString();

หากคุณมี url เช่นhttp://base_path/some_segment/idคุณสามารถทำได้

final Path urlPath = Paths.get("http://base_path/some_segment/id");
final Path lastSegment = urlPath.getName(urlPath.getNameCount() - 1);

4
มีความเสี่ยงเนื่องจาก java.nio.file.Paths # get ขึ้นอยู่กับระบบไฟล์ OS ที่ JVM ทำงานอยู่ ไม่มีการรับประกันว่าจะจดจำ URI โดยมีเครื่องหมายทับเป็นตัวคั่นเส้นทาง
Adrian Baker

2
สิ่งที่เกี่ยวกับ URI กับพารามิเตอร์แบบสอบถาม การจัดการ URI แบบสุ่มเป็นพา ธ ระบบไฟล์กำลังขอให้มีข้อยกเว้น
Abhijit Sarkar

9

ใน Android

Android มีคลาสในตัวสำหรับจัดการ URI

Uri uri = Uri.parse("http://base_path/some_segment/id");
String lastPathSegment = uri.getLastPathSegment()

บางครั้งสิ่งนี้ก็พ่นออกมาเต็มเส้นทาง ไม่แน่ใจว่าทำไมหรือเมื่อใดจึงเป็นแบบสุ่ม
MobDev

หากคุณสามารถจับเนื้อหาที่กำลังแยกวิเคราะห์คุณอาจตั้งค่าการทดสอบหน่วยเพื่อให้แน่ใจ
Brill Pappin

8

ใน Java 7+ สามารถรวมคำตอบก่อนหน้าสองสามคำเพื่ออนุญาตให้ดึงส่วนเส้นทางใด ๆจาก URI แทนที่จะเป็นเพียงส่วนสุดท้าย เราสามารถแปลง URI เป็นjava.nio.file.Pathวัตถุเพื่อใช้ประโยชน์จากgetName(int)วิธีการของมัน

น่าเสียดายที่โรงงานแบบคงที่Paths.get(uri)ไม่ได้สร้างขึ้นเพื่อจัดการกับโครงร่าง http ดังนั้นก่อนอื่นเราต้องแยกโครงร่างออกจากเส้นทางของ URI

URI uri = URI.create("http://base_path/some_segment/id");
Path path = Paths.get(uri.getPath());
String last = path.getFileName().toString();
String secondToLast = path.getName(path.getNameCount() - 2).toString();

หากต้องการรับส่วนสุดท้ายในโค้ดบรรทัดเดียวให้ซ้อนบรรทัดด้านบน

Paths.get(URI.create("http://base_path/some_segment/id").getPath()).getFileName().toString()

หากต้องการรับส่วนที่สองถึงสุดท้ายในขณะที่หลีกเลี่ยงตัวเลขดัชนีและโอกาสที่จะเกิดข้อผิดพลาดแบบ off-by-one ให้ใช้getParent()วิธีนี้

String secondToLast = path.getParent().getFileName().toString();

โปรดสังเกตว่าgetParent()เมธอดสามารถถูกเรียกซ้ำ ๆ เพื่อดึงเซ็กเมนต์ในลำดับย้อนกลับ ในตัวอย่างนี้พา ธ มีเพียงสองเซ็กเมนต์เท่านั้นมิฉะนั้นการโทรgetParent().getParent()จะดึงเซ็กเมนต์ที่สามถึงสุดท้าย


6

หากคุณcommons-ioรวมไว้ในโครงการของคุณคุณสามารถทำได้โดยไม่ต้องสร้างวัตถุที่ไม่จำเป็นด้วยorg.apache.commons.io.FilenameUtils

String uri = "http://base_path/some_segment/id";
String fileName = FilenameUtils.getName(uri);
System.out.println(fileName);

จะให้ส่วนสุดท้ายของพา ธ ซึ่งก็คือ id


3

คุณสามารถใช้getPathSegments()ฟังก์ชัน ( เอกสาร Android )

พิจารณา URI ตัวอย่างของคุณ:

String uri = "http://base_path/some_segment/id"

คุณสามารถรับกลุ่มสุดท้ายโดยใช้:

List<String> pathSegments = uri.getPathSegments();
String lastSegment = pathSegments.get(pathSegments.size - 1);

lastSegmentidจะเป็น


1

คุณยังสามารถใช้ replaceAll:

String uri = "http://base_path/some_segment/id"
String lastSegment = uri.replaceAll(".*/", "")

System.out.println(lastSegment);

ผลลัพธ์:

id

0

ฉันใช้สิ่งต่อไปนี้ในคลาสยูทิลิตี้:

public static String lastNUriPathPartsOf(final String uri, final int n, final String... ellipsis)
  throws URISyntaxException {
    return lastNUriPathPartsOf(new URI(uri), n, ellipsis);
}

public static String lastNUriPathPartsOf(final URI uri, final int n, final String... ellipsis) {
    return uri.toString().contains("/")
        ? (ellipsis.length == 0 ? "..." : ellipsis[0])
          + uri.toString().substring(StringUtils.lastOrdinalIndexOf(uri.toString(), "/", n))
        : uri.toString();
}

-1

รับ URL จาก URI และใช้ getFile () หากคุณไม่พร้อมที่จะใช้วิธีการแตกไฟล์ย่อย


2
ใช้งานไม่ได้โปรดดู javadoc ของ getFile (): รับชื่อไฟล์ของ URL นี้ ส่วนของไฟล์ที่ส่งคืนจะเหมือนกับ getPath () บวกกับการต่อค่าของ getQuery () ถ้ามี หากไม่มีส่วนการค้นหาวิธีนี้และ getPath () จะให้ผลลัพธ์ที่เหมือนกัน)
sfussenegger

ใช้ไม่ได้getPath() getFile()
Jason C
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.