Làm cách nào để giải mã URL trong Java?


323

Trong Java, tôi muốn chuyển đổi cái này:

https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do%3Frequest_type

Về điều này:

https://mywebsite/docs/english/site/mybook.do&request_type

Đây là những gì tôi có cho đến nay:

class StringUTF 
{
    public static void main(String[] args) 
    {
        try{
            String url = 
               "https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do" +
               "%3Frequest_type%3D%26type%3Dprivate";

            System.out.println(url+"Hello World!------->" +
                new String(url.getBytes("UTF-8"),"ASCII"));
        }
        catch(Exception E){
        }
    }
}

Nhưng nó không hoạt động đúng. Chúng %3A%2Fcác định dạng được gọi là gì và làm cách nào để chuyển đổi chúng?


@Stephen .. Tại sao url không thể là Chuỗi được mã hóa UTF-8 ..?
crackerplace

Vấn đề là chỉ vì URL có thể là UTF-8, câu hỏi thực sự không liên quan gì đến UTF-8. Tôi đã chỉnh sửa câu hỏi phù hợp.
Chris Jester-Young

Nó có thể là (về lý thuyết) nhưng chuỗi trong ví dụ của bạn không phải là Chuỗi được mã hóa UTF-8. Nó là một chuỗi ASCII được mã hóa URL. Do đó tiêu đề là sai lệch.
Stephen C

Cũng cần lưu ý rằng tất cả các ký tự trong urlchuỗi là ASCII và điều này cũng đúng sau khi chuỗi đã được giải mã URL. '%'là một char ASCII và %xxđại diện cho một char ASCII nếu xxnhỏ hơn (hexadecimal) 80.
Stephen C

Câu trả lời:


634

Điều này không liên quan gì đến mã hóa ký tự như UTF-8 hoặc ASCII. Chuỗi bạn có có URL được mã hóa . Loại mã hóa này là một cái gì đó hoàn toàn khác với mã hóa ký tự.

Hãy thử một cái gì đó như thế này:

try {
    String result = java.net.URLDecoder.decode(url, StandardCharsets.UTF_8.name());
} catch (UnsupportedEncodingException e) {
    // not going to happen - value came from JDK's own StandardCharsets
}

Java 10 đã thêm hỗ trợ trực tiếp cho CharsetAPI, có nghĩa là không cần phải bắt UnsupportedEncodingException:

String result = java.net.URLDecoder.decode(url, StandardCharsets.UTF_8);

Lưu ý rằng mã hóa ký tự (chẳng hạn như UTF-8 hoặc ASCII) là yếu tố quyết định ánh xạ các ký tự thành byte thô. Đối với một giới thiệu tốt để mã hóa nhân vật, xem bài viết này .


1
Các phương thức trên URLDecoderlà tĩnh nên bạn không phải tạo phiên bản mới của nó.
laz

2
@Trismegistos Chỉ phiên bản mà bạn không chỉ định mã hóa ký tự (tham số thứ hai "UTF-8") không được chấp nhận theo tài liệu API của Java 7. Sử dụng phiên bản có hai tham số.
Jesper

23
Nếu sử dụng java 1.7+, bạn có thể sử dụng phiên bản tĩnh của chuỗi "UTF-8": StandardCharsets.UTF_8.name()từ gói này : java.nio.charset.StandardCharsets. Liên quan đến điều này: link
Shahar

1
Đối với mã hóa ký tự, điều này làm cho một bài viết tuyệt vời quá balusc.blogspot.in/2009/05/unicode-how-to-get-char character
right.html

4
Hãy cẩn thận với điều này. Như đã lưu ý ở đây: blog.lunatech.com/2009/02/03/ Khăn Đây không phải là về URL, mà là mã hóa biểu mẫu HTML.
Michal

52

Chuỗi bạn có là application/x-www-form-urlencodedmã hóa.

Sử dụng URLDecoder để chuyển đổi nó thành Chuỗi Java.

URLDecoder.decode( url, "UTF-8" );

47

Điều này đã được trả lời trước đây (mặc dù câu hỏi này là lần đầu tiên!):

"Bạn nên sử dụng java.net.URI để làm điều này, vì lớp URLDecoder thực hiện giải mã x-www-form-urlencoding sai (mặc dù tên, đó là cho dữ liệu biểu mẫu)."

Như tài liệu lớp URL nêu:

Cách được đề xuất để quản lý mã hóa và giải mã URL là sử dụng URI và chuyển đổi giữa hai lớp này bằng cách sử dụng toURI ()URI.toURL () .

Các lớp URLEncoderURLDecoder cũng có thể được sử dụng, nhưng chỉ cho mã hóa biểu mẫu HTML, không giống như sơ đồ mã hóa được định nghĩa trong RFC2394 .

Về cơ bản:

String url = "https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do%3Frequest_type";
System.out.println(new java.net.URI(url).getPath());

sẽ cung cấp cho bạn:

https://mywebsite/docs/english/site/mybook.do?request_type

6
Trong Java 1.7, URLDecoder.decode(String, String)tình trạng quá tải không được phản đối. Bạn phải đề cập đến URLDecoder.decode(String)quá tải mà không cần mã hóa. Bạn có thể muốn cập nhật bài viết của mình để làm rõ.
Aaron

2
Câu trả lời này là sai lệch; trích dẫn khối đó không có gì để làm với sự phản đối. Javadoc của các phương thức không dùng nữa và tôi thực sự trích dẫn@deprecated The resulting string may vary depending on the platform's default encoding. Instead, use the decode(String,String) method to specify the encoding.
Emerson Farrugia

1
getPath () cho các URI chỉ trả về phần đường dẫn của URI, như đã lưu ý ở trên.
Pelpotronic

2
Trừ khi tôi nhầm, "đường dẫn" được biết là một phần của URI sau phần quyền (xem: en.wikipedia.org/wiki/Uniform_Resource_Identifier để định nghĩa đường dẫn) - dường như đối với tôi hành vi tôi đang thấy là hành vi chuẩn / đúng. Tôi đang sử dụng java 1.8.0_101 (trên Android Studio). Tôi tò mò muốn xem những gì bạn nhận được là "getAuthority ()" được gọi. Ngay cả bài viết / ví dụ này dường như chỉ ra rằng đường dẫn chỉ là phần / công khai / thủ công / thiết bị trong URI của họ: quepublishing.com/articles/article.aspx?p=26566&seqNum=3
Pelpotronic

1
@Pelpotronic Mã trong bài viết thực sự in kết quả đầu ra mà nó hiển thị (ít nhất là đối với tôi). Tôi nghĩ lý do cho điều này là vì mã hóa URL, hàm tạo URI thực sự đang xử lý toàn bộ chuỗi, ( https%3A%2F...), giống như đường dẫn của URI; không có thẩm quyền hoặc truy vấn, v.v. Điều này có thể được kiểm tra bằng cách gọi các phương thức get tương ứng trên đối tượng URI. Nếu bạn chuyển văn bản được giải mã cho hàm tạo URI : new URI("https://mywebsite/do....."), thì việc gọi getPath()và các phương thức khác sẽ cho kết quả chính xác.
Kröw

14

%3A%2Flà các ký tự được mã hóa URL. Sử dụng mã java này để chuyển đổi chúng trở lại :/

String decoded = java.net.URLDecoder.decode(url, "UTF-8");

2
nó cũng không chuyển đổi% 2C, đó là (,)
vuhung3990

cái này cần được gói trong một khối thử / bắt .. đọc thêm về các ngoại lệ được kiểm tra (cái này) so với stackoverflow.com/questions/6115896/ Lỗi
Bruno Wolff

5
 try {
        String result = URLDecoder.decode(urlString, "UTF-8");
    } catch (UnsupportedEncodingException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

5
public String decodeString(String URL)
    {

    String urlString="";
    try {
        urlString = URLDecoder.decode(URL,"UTF-8");
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block

        }

        return urlString;

    }

4
Bạn có thể vui lòng giải thích thêm câu trả lời của bạn thêm một chút mô tả về giải pháp bạn cung cấp không?
abarisone


2
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;

public class URLDecoding { 

    String decoded = "";

    public String decodeMethod(String url) throws UnsupportedEncodingException
    {
        decoded = java.net.URLDecoder.decode(url, "UTF-8"); 
        return  decoded;
//"You should use java.net.URI to do this, as the URLDecoder class does x-www-form-urlencoded decoding which is wrong (despite the name, it's for form data)."
    }

    public String getPathMethod(String url) throws URISyntaxException 
    {
        decoded = new java.net.URI(url).getPath();  
        return  decoded; 
    }

    public static void main(String[] args) throws UnsupportedEncodingException, URISyntaxException 
    {
        System.out.println(" Here is your Decoded url with decode method : "+ new URLDecoding().decodeMethod("https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do%3Frequest_type")); 
        System.out.println("Here is your Decoded url with getPath method : "+ new URLDecoding().getPathMethod("https%3A%2F%2Fmywebsite%2Fdocs%2Fenglish%2Fsite%2Fmybook.do%3Frequest")); 

    } 

}

Bạn có thể chọn phương pháp của mình một cách khôn ngoan :)


0

Sử dụng lớp java.net.URI:

public String getDecodedURL(String encodedUrl) {
    try {
        URI uri = new URI(encodedUrl);
        return uri.getScheme() + ":" + uri.getSchemeSpecificPart();
    } catch (Exception e) {
        return "";
    }
}

Xin lưu ý rằng xử lý ngoại lệ có thể tốt hơn, nhưng nó không liên quan nhiều đến ví dụ này.

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.