จะถอดรหัส URL ใน Java ได้อย่างไร?


323

ใน Java ฉันต้องการแปลงสิ่งนี้:

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

สำหรับสิ่งนี้:

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

นี่คือสิ่งที่ฉันมี:

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){
        }
    }
}

แต่มันไม่ทำงาน สิ่งเหล่านี้%3Aและ%2Fรูปแบบที่เรียกว่าอะไรและฉันจะแปลงได้อย่างไร


@ สตีเฟน .. ทำไม URL ไม่สามารถเป็นสตริงที่เข้ารหัส UTF-8 ได้ ..
crackerplace

ปัญหาคือเพียงเพราะ URL สามารถเป็น UTF-8 คำถามนี้ไม่มีส่วนเกี่ยวข้องกับ UTF-8 ฉันแก้ไขคำถามอย่างเหมาะสม
Chris Jester-Young

อาจเป็น (ในทางทฤษฎี) แต่สตริงในตัวอย่างของคุณไม่ใช่สตริงที่เข้ารหัส UTF-8 มันเป็นสตริง ASCII ที่เข้ารหัส URL ดังนั้นชื่อเรื่องนั้นทำให้เข้าใจผิด
สตีเฟ่นซี

นอกจากนี้ยังเป็นที่น่าสังเกตว่าอักขระทั้งหมดในurlสตริงเป็น ASCII และสิ่งนี้ก็เป็นจริงเช่นกันหลังจากที่สตริงนั้นได้รับการถอดรหัส URL '%'เป็นถ่าน ASCII และ%xxแสดงให้เห็นถึงถ่าน ASCII ถ้าxxน้อยกว่า 80(เลขฐานสิบหก)
สตีเฟ่นซี

คำตอบ:


634

สิ่งนี้ไม่มีส่วนเกี่ยวข้องกับการเข้ารหัสอักขระเช่น UTF-8 หรือ ASCII สตริงที่คุณต้องมีURL ที่เข้ารหัส การเข้ารหัสชนิดนี้เป็นสิ่งที่แตกต่างอย่างสิ้นเชิงจากการเข้ารหัสอักขระ

ลองสิ่งนี้:

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 เพิ่มการรองรับโดยตรงสำหรับCharsetAPI ซึ่งหมายความว่าไม่จำเป็นต้องจับ UnsupportedEncodingException:

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

โปรดทราบว่าการเข้ารหัสอักขระ (เช่น UTF-8 หรือ ASCII) เป็นสิ่งที่กำหนดการแมปของอักขระเป็นไบต์ดิบ สำหรับช่วงแนะนำที่ดีในการเข้ารหัสตัวอักษรดูบทความนี้


1
วิธีการที่URLDecoderเป็นแบบคงที่ดังนั้นคุณไม่จำเป็นต้องสร้างอินสแตนซ์ใหม่ของมัน
laz

2
@Trismegistos เฉพาะรุ่นที่คุณไม่ได้ระบุการเข้ารหัสอักขระ (พารามิเตอร์ตัวที่สอง"UTF-8") ถูกคัดค้านตามเอกสาร Java 7 API ใช้เวอร์ชันที่มีสองพารามิเตอร์
Jesper

23
ถ้าใช้ Java 1.7+ คุณสามารถใช้รุ่นที่คงที่ของ "UTF-8" สตริง: จากแพคเกจนี้:StandardCharsets.UTF_8.name() java.nio.charset.StandardCharsetsเกี่ยวข้องกับสิ่งนี้: ลิงก์
Shahar

1
สำหรับการเข้ารหัสตัวละครนี้จะทำให้บทความดีดี balusc.blogspot.in/2009/05/unicode-how-to-get-characters-right.html เกินไป
crackerplace

4
ระวังด้วยนะ ดังที่ระบุไว้ที่นี่: blog.lunatech.com/2009/02/03/… นี่ไม่ได้เกี่ยวกับ URL แต่สำหรับการเข้ารหัสฟอร์ม HTML
มิคาล


47

คำตอบนี้ได้รับก่อน (แม้ว่าคำถามนี้เป็นครั้งแรก!):

"คุณควรใช้ java.net.URI เพื่อทำสิ่งนี้เนื่องจากคลาส URLDecoder ทำการถอดรหัส x-www-form-urlencoded ซึ่งผิด (แม้ว่าชื่อจะเป็นข้อมูลแบบฟอร์ม)"

ในฐานะที่เป็นเอกสารประกอบคลาสURL :

วิธีที่แนะนำในการจัดการการเข้ารหัสและถอดรหัสของ URL ที่คือการใช้URIและการแปลงระหว่างทั้งสองเรียนโดยใช้Touri ()และ URI.toURL ()

URLEncoderและURLDecoderเรียนนอกจากนี้ยังสามารถนำมาใช้ แต่เพียงสำหรับการเข้ารหัสรูปแบบ HTML, ซึ่งไม่ได้เป็นเช่นเดียวกับการเข้ารหัสรูปแบบที่กำหนดไว้ในRFC2396

โดยทั่วไป:

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

จะให้:

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

6
ใน Java 1.7 การURLDecoder.decode(String, String)โอเวอร์โหลดไม่ได้ถูกเลิกใช้ คุณต้องอ้างถึงURLDecoder.decode(String)โอเวอร์โหลดโดยไม่ต้องเข้ารหัส คุณอาจต้องการอัพเดทโพสต์ของคุณเพื่อความกระจ่าง
แอรอน

2
คำตอบนี้ทำให้เข้าใจผิด; การอ้างอิงบล็อกนั้นไม่มีส่วนเกี่ยวข้องกับการคัดค้าน Javadoc ของวิธีการที่เลิกใช้แล้วและฉันเสนอราคาจริงๆ@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 () สำหรับ URIs จะคืนค่าพา ธ ส่วนหนึ่งของ URI ดังที่ระบุไว้ข้างต้น
Pelpotronic

2
เว้นแต่ว่าฉันเข้าใจผิด "เส้นทาง" เป็นที่รู้จักกันว่าเป็นส่วนหนึ่งของ URI หลังจากส่วนของอำนาจ (ดู: en.wikipedia.org/wiki/Uniform_Resource_Identifierสำหรับคำจำกัดความของเส้นทาง) - ดูเหมือนว่าพฤติกรรมที่ฉันเห็น เป็นพฤติกรรมมาตรฐาน / ถูกต้อง ฉันใช้ java 1.8.0_101 (บน Android Studio) ฉันอยากรู้ว่าคุณได้รับอะไรในฐานะ "getAuthority ()" ถูกเรียก แม้แต่บทความ / ตัวอย่างนี้ดูเหมือนว่าบ่งบอกว่าเส้นทางเป็นเพียงส่วน / สาธารณะ / คู่มือ / appliances ของ URI ของพวกเขา: quepublishing.com/articles/article.aspx?p=26566&seqNum=3
Pelpotronic

1
@ Pelpotronic รหัสในโพสต์จริง ๆ แล้วพิมพ์ผลลัพธ์ที่มันแสดง (อย่างน้อยสำหรับฉัน) ฉันคิดว่าเหตุผลของเรื่องนี้ก็คือเพราะการเข้ารหัส URL คอนสตรัคเตอร์ URI นั้นปฏิบัติต่อสตริงทั้งหมด ( https%3A%2F...) เหมือนกับเส้นทางของ URI ไม่มีสิทธิ์หรือคิวรีเป็นต้นซึ่งสามารถทดสอบได้โดยการเรียกเมธอด get ตามลำดับบนอ็อบเจ็กต์ URI หากคุณส่งข้อความที่ถอดรหัสไปยังตัวสร้าง URI: การnew URI("https://mywebsite/do.....")โทรgetPath()และวิธีอื่น ๆ จะให้ผลลัพธ์ที่ถูกต้อง
Kröw

14

%3Aและ%2Fเป็นอักขระที่เข้ารหัส URL ใช้รหัส java นี้เพื่อแปลงกลับเป็น:และ/

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

2
มันไม่ได้แปลง% 2C ด้วยเช่นกันคือ (,)
vuhung3990

ต้องห่อในบล็อก try / catch .. อ่านเพิ่มเติมเกี่ยวกับข้อยกเว้นที่ตรวจสอบ (อันนี้) เทียบกับstackoverflow.com/questions/6115896/…ที่
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
คุณช่วยอธิบายรายละเอียดเพิ่มเติมเกี่ยวกับโซลูชันที่คุณให้ได้ไหม
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")); 

    } 

}

คุณสามารถเลือกวิธีการของคุณอย่างชาญฉลาด :)


0

ใช้คลาส java.net.URI:

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

โปรดทราบว่าการจัดการข้อยกเว้นสามารถทำได้ดีกว่า แต่ก็ไม่เกี่ยวข้องกับตัวอย่างนี้มากนัก

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