URIの最後のパスセグメントを取得する方法


114

入力として、である文字列がありURIます。最後のパスセグメント(私の場合はid)を取得するにはどうすればよいですか?

これは私の入力URLです。

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

そして私はこれで試した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のandroid.net.Uri(java.net.URIではない)を検索していて、ここに到達しました。代わりにそれを使用している場合は、同じことを行うはずのgetLastPathSegment()というメソッドがあります。:)
pm_labs 2013年

5
String idStr = new File(uri.getPath()).getName()この答えと同じですが、パスを分割するFile代わりに使用Stringします。
Jason C

これは、example.com/ job/senior-health-and-nutrition-advisor/?param=trueのようなURLでは機能しません。最後の「/」は困っています。@paul_snsによって提供されるgetLastPathSegment()のより良い何かが必要です。
Vaibhav Kadam

@VaibhavKadamよく、技術的には最後のセグメントは空の文字列であると主張できます。しかし、それが単に使用したくないものである場合:while (path.endsWith("/")) path = path.substring(0, path.length() - 1);
sfussenegger

@sfussenegger問題のタグを読みませんでした。androidのタグがあると思いました。よくandroid.net.uriの+1。:)。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

また、Android Uriクラス名は小文字であり、インスタンス化することはできません。静的ファクトリメソッドを使用するように回答を修正しましたUri.parse()
2015年

GetLastPathSegmentはここには存在しません。
Abdullah Shoaib 2015

2
getLastPathSegment()はありますが、機能しません!nullを返します!
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

私は正規表現の大ファンであり、私自身も頻繁に使用していますが、ほとんどの開発者にとって、正規表現はそれと同じくらい鈍感であることを認識しています。それはすぐに理解されないという事実において単純ではありません。
Bill Turner

/否定文字クラス内では[^/?]、それが一致することはありませんので、不要です。.*/は常に文字列の最後 /と一致するため、他/に遭遇することはありません。
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();

http://base_path/some_segment/idあなたができるようなURLを持っている場合。

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は、JVMが実行されているOSファイルシステムに依存するため、危険です。パスの区切り文字としてスラッシュを含むURIが認識される保証はありません。
エイドリアン・ベイカー

2
クエリパラメータを使用したURIについてはどうですか?ランダムなURIをファイルシステムパスとして扱うには、例外が必要です。
Abhijit Sarkar 2017年

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から任意のパスセグメントを取得できます。java.nio.file.PathそのgetName(int)メソッドを利用するために、URIをオブジェクトに変換できます。

残念ながら、静的ファクトリ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();

コードの1行の最後のセグメントを取得するには、単に上記の行をネストします。

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

最後から2番目のセグメントを取得し、インデックス番号と1つずれるエラーの可能性を回避するには、getParent()メソッドを使用します。

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

このgetParent()メソッドを繰り返し呼び出して、逆の順序でセグメントを取得できることに注意してください。この例では、パスには2つのセグメントのみが含まれています。それ以外の場合、呼び出しgetParent().getParent()は最後から3番目のセグメントを取得します。


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

lastSegmentになりますid


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

URIからURLを取得し、部分文字列でファイルを抽出する準備ができていない場合はgetFile()を使用します。


2
動作しません。getFile()のjavadocを参照してください:このURLのファイル名を取得します。返されるファイル部分は、getPath()と同じですが、getQuery()の値があれば、それを連結したものになります。クエリ部分がない場合、このメソッドとgetPath()は同じ結果を返します。)
sfussenegger

使用しgetPath()ないでくださいgetFile()
Jason C
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.