URLEncoder अंतरिक्ष वर्ण का अनुवाद करने में सक्षम नहीं है


179

मैं उम्मीद करता हूँ

System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8"));

उत्पादन के लिए:

Hello%20World

(अंतरिक्ष के लिए 20 ASCII हेक्स कोड है)

हालाँकि, मुझे जो मिलता है वह है:

Hello+World

क्या मैं गलत तरीके का उपयोग कर रहा हूँ? मेरे द्वारा उपयोग की जाने वाली सही विधि क्या है?


3
वर्ग नाम वास्तव में भ्रामक है, और कई लोगों ने इसका गलत तरीके से उपयोग किया है। हालाँकि, वे इसे नोटिस नहीं करते हैं, क्योंकि जब URLDecoder लागू होता है, तो मूल मूल्य बहाल हो जाता है, इसलिए + या% 20 उनके लिए वास्तव में मायने नहीं रखता है।
अपरिवर्तनीय

जवाबों:


227

यह अपेक्षा के अनुरूप व्यवहार करता है। URLEncoderHTML रूपों में URL को कैसे एन्कोड किया जाए, इसके लिए HTML विनिर्देश लागू करता है।

से javadocs :

इस वर्ग में एक स्ट्रिंग को एप्लिकेशन / x-www-form-urlencoded MIME प्रारूप में परिवर्तित करने के लिए स्थैतिक विधियाँ हैं।

और HTML विशिष्टता से :

आवेदन / x-www फार्म-urlencoded

इस सामग्री प्रकार के साथ जमा किए गए प्रपत्र निम्नानुसार एन्कोड किए जाने चाहिए:

  1. नियंत्रण नाम और मूल्य बच गए हैं। अंतरिक्ष पात्रों को '+' से बदल दिया जाता है

आपको इसे बदलना होगा, जैसे:

System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replace("+", "%20"));

19
अच्छी तरह से यह एक जवाब है वास्तव में, जगह के बजाय एक जावा पुस्तकालय या कार्य करने के लिए एक समारोह नहीं है /?
co2f2e

5
प्लस चिन्ह से बचने की जरूरत हैt.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replace("\\+", "%20"));
जॉर्ज

26
@congliu गलत है - आप शायद रीप्लेस () के बारे में सोच रहे हैं जो रेगेक्स के साथ काम करता है - रिप्लेस () सरल चरित्र अनुक्रम प्रतिस्थापन है।
क्यूपॉन्टेएए सेप

12
हाँ @congliu अच्छा तरीका है: URLEncoder.encode ("Myurl", "utf-8")।
eento

9
@ClintEastwood यह उत्तर java.net.URLEncoder के उपयोग को प्रोत्साहित करता है जो मूल रूप से पूछा गया काम नहीं करता है। और इसलिए यह उत्तर एक पैच का सुझाव देता है, इसके शीर्ष पर प्रतिस्थापित () का उपयोग करके। क्यों नहीं? क्योंकि यह समाधान बग प्रवण है और इसी तरह के 20 अन्य प्रश्नों को जन्म दे सकता है लेकिन एक अलग चरित्र के साथ। इसीलिए मैंने कहा कि यह छोटा था।
pyb

57

एक स्थान %20URL और, में एन्कोड किया गया है+ सबमिट किए गए डेटा (सामग्री प्रकार अनुप्रयोग / x-www-form-urlencoded) रूपों में । आपको पूर्व की आवश्यकता है।

अमरूद का उपयोग :

dependencies {
     compile 'com.google.guava:guava:23.0'
     // or, for Android:
     compile 'com.google.guava:guava:23.0-android'
}

आप UrlEscapers का उपयोग कर सकते हैं :

String encodedString = UrlEscapers.urlFragmentEscaper().escape(inputString);

String.replace का उपयोग न करें, इससे केवल स्थान घेरता है। इसके बजाय किसी लाइब्रेरी का उपयोग करें।


यह एंड्रॉइड के लिए भी काम करता है। com.google.guava: guava: 22.0-rc1-android।
Bevor

1
@Bevor rc1 का अर्थ है 1 रिलीज़ कैंडिडेट, यानी सामान्य रिलीज़ के लिए अभी तक अनुमोदित नहीं किया गया संस्करण। यदि आप कर सकते हैं, बिना स्नैपशॉट, अल्फा, बीटा, आरसी के एक संस्करण चुनें, क्योंकि वे बग को शामिल करने के लिए जाने जाते हैं।
pyb

1
@pyb थैंक्स, लेकिन मैं वैसे भी लिबास को अपडेट करूंगा जब मेरा प्रोजेक्ट खत्म हो जाएगा। मतलब, मैं अंतिम संस्करणों के बिना ठेस नहीं जाऊंगा। और अभी भी कई सप्ताह लगते हैं, इसलिए मुझे लगता है कि फिर एक अंतिम संस्करण है।
Bevor

1
दुर्भाग्य से, अमरूद अपाचे के यूआरएलकोड के विपरीत, एक डिकोडर प्रदान नहीं करता है ।
बेनी बोटेमा

26

यह वर्ग application/x-www-form-urlencodedप्रतिशत एन्कोडिंग के बजाय-एन्कोडिंग निष्पादित करता है , इसलिए इसके साथ प्रतिस्थापित करना +एक सही व्यवहार है।

जावदोक से:

स्ट्रिंग को एन्कोडिंग करते समय, निम्नलिखित नियम लागू होते हैं:

  • अल्फ़ान्यूमेरिक वर्ण "ए" के माध्यम से "जेड", "ए" के माध्यम से "जेड" और "0" के माध्यम से "9" समान रहते हैं।
  • विशेष वर्ण "।", "-", "*", और "_" समान रहते हैं।
  • अंतरिक्ष चरित्र "" को प्लस चिह्न "+" में परिवर्तित किया जाता है।
  • अन्य सभी वर्ण असुरक्षित हैं और पहले कुछ एन्कोडिंग योजना का उपयोग करके एक या एक से अधिक बाइट में परिवर्तित हो जाते हैं। फिर प्रत्येक बाइट को 3-वर्ण स्ट्रिंग "% xy" द्वारा दर्शाया जाता है, जहां xy बाइट के दो-अंकीय हेक्साडेसिमल प्रतिनिधित्व है। उपयोग करने के लिए अनुशंसित एन्कोडिंग योजना UTF-8 है। हालाँकि, संगतता कारणों के लिए, यदि एन्कोडिंग निर्दिष्ट नहीं है, तो प्लेटफ़ॉर्म की डिफ़ॉल्ट एन्कोडिंग का उपयोग किया जाता है।

@axtavt अच्छा स्पष्टीकरण। लेकिन मेरे पास अभी भी कुछ सवाल हैं। में url, अंतरिक्ष के रूप में व्याख्या की जानी चाहिए %20। तो हमें करने की आवश्यकता है url.replaceAll("\\+", "%20")? और अगर यह जावास्क्रिप्ट है, तो हमें escapeफ़ंक्शन का उपयोग नहीं करना चाहिए । उपयोग encodeURIया encodeURIComponentइसके बजाय। बिल्कुल यही मैने सोचा।
एलस्टन

1
@Stallman यह जावा है, जावास्क्रिप्ट नहीं। पूरी तरह से विभिन्न भाषाओं।
चार्ल्स वुड

19

क्वेरी पैरामेड्स को एनकोड करें

org.apache.commons.httpclient.util.URIUtil
    URIUtil.encodeQuery(input);

या यदि आप URI के भीतर चार्ट से बचना चाहते हैं

public static String escapeURIPathParam(String input) {
  StringBuilder resultStr = new StringBuilder();
  for (char ch : input.toCharArray()) {
   if (isUnsafe(ch)) {
    resultStr.append('%');
    resultStr.append(toHex(ch / 16));
    resultStr.append(toHex(ch % 16));
   } else{
    resultStr.append(ch);
   }
  }
  return resultStr.toString();
 }

 private static char toHex(int ch) {
  return (char) (ch < 10 ? '0' + ch : 'A' + ch - 10);
 }

 private static boolean isUnsafe(char ch) {
  if (ch > 128 || ch < 0)
   return true;
  return " %$&+,/:;=?@<>#%".indexOf(ch) >= 0;
 }

3
का उपयोग करते हुए org.apache.commons.httpclient.util.URIUtilइस मुद्दे को हल करने के लिए सबसे कारगर तरीका प्रतीत हो रहा है!
स्टीफन अम्मार

11

Hello+Worldयह है कि कैसे ब्राउज़र अनुरोध के application/x-www-form-urlencodedलिए फ़ॉर्म डेटा ( ) को एन्कोड करेगा GETऔर यह एक URI के क्वेरी भाग के लिए आम तौर पर स्वीकृत फ़ॉर्म है।

http://host/path/?message=Hello+World

यदि आपने जावा सर्वलेट के लिए यह अनुरोध भेजा है, तो सर्वलेट पैरामीटर मान को सही ढंग से डिकोड करेगा। आमतौर पर केवल एक बार यहाँ समस्याएँ होती हैं यदि एन्कोडिंग मेल नहीं खाता है।

कड़ाई से बोलते हुए, HTTP या URI चश्मे में कोई आवश्यकता नहीं है कि application/x-www-form-urlencodedकुंजी-मूल्य जोड़े का उपयोग करके क्वेरी भाग को एन्कोड किया जाए ; क्वेरी भाग को वेब सर्वर के रूप में स्वीकार करने की आवश्यकता है। व्यवहार में, यह एक मुद्दा होने की संभावना नहीं है।

यूआरआई के अन्य हिस्सों (उदाहरण के लिए पथ) के लिए इस एन्कोडिंग का उपयोग करना आमतौर पर गलत होगा। उस स्थिति में, आपको RFC 3986 में वर्णित एन्कोडिंग योजना का उपयोग करना चाहिए ।

http://host/Hello%20World

अधिक यहाँ


5

अन्य उत्तर या तो एक मैनुअल स्ट्रिंग प्रतिस्थापन, URLEncoder प्रस्तुत करते हैं जो वास्तव में HTML प्रारूप के लिए एन्कोड होता है, अपाचे का परित्याग URIUtil , या अमरूद के UrlEscapers का उपयोग करके । अंतिम एक ठीक है, सिवाय इसके कि यह एक डिकोडर प्रदान नहीं करता है।

Apache Commons Lang URLCodec प्रदान करता है , जो URL प्रारूप rfc3986 के अनुसार एन्कोड और डिकोड करता है ।

String encoded = new URLCodec().encode(str);
String decoded = new URLCodec().decode(str);

यदि आप पहले से ही स्प्रिंग का उपयोग कर रहे हैं, तो आप इसके यूरीटिल्स वर्ग का भी उपयोग करने का विकल्प चुन सकते हैं ।


6
URLCodec यहां एक अच्छा समाधान नहीं है क्योंकि यह प्लसस के रूप में रिक्त स्थान को एन्कोड करता है, लेकिन सवाल यह है कि रिक्त स्थान को 20% तक एन्कोड किया जाए।
davidwebster48

3

"+" सही है। यदि आपको वास्तव में% 20 की आवश्यकता है, तो बाद में अपने आप को प्लेसेस बदलें।


5
एक समस्या हो सकती है यदि प्रारंभिक स्ट्रिंग में वास्तव में एक + चरित्र है।
एलेक्सिस डुफ्रेनॉय

17
@ टैरोथ - वास्तव में नहीं। +मूल पाठ में एक वर्ण के रूप में एन्कोड किया गया माना जाता है %2B
टेड हॉप

यह कहना कि +संदर्भ को जाने बिना सही है, कम से कम, पांडित्य। Downvoted। + या% 20 का उपयोग कब किया जाना है, इसके बारे में जानने के लिए अन्य उत्तर पढ़ें।
क्लिंट ईस्टवुड

@ क्लिंटएस्टवुड: क्या आप मुझे किसी भी usecase के बारे में बता सकते हैं कि रिक्त स्थान के लिए वर्ण URL में सही नहीं है? सिवाय इसके कि दूसरी तरफ गैर-अनुरूपण URL पार्सर कब है?
डेनियल

@ डैनियल यकीन है, "गलत" नहीं बल्कि अनुपयुक्त? हाँ। Analytics टूल अक्सर किसी निश्चित वर्ण द्वारा अलग किए गए मानों के साथ क्वेरी परम का उपयोग करते हैं, उदाहरण के लिए "+"। उस स्थिति में, "% 20" के बजाय "+" का उपयोग करना गलत होगा। "+" का उपयोग रिक्त स्थान से बचने के लिए किया जाता है, जबकि "प्रतिशत एन्कोडिंग" (उर्फ URL एन्कोडिंग) URL के लिए अधिक उन्मुख है।
क्लिंट ईस्टवुड

3

एंड्रॉइड पर बस इसके साथ संघर्ष कर रहा था, Uri.encode (स्ट्रिंग, स्ट्रिंग) पर ठोकर खाने में कामयाब रहा, जबकि एंड्रॉइड के लिए विशिष्ट (android.net.Uri) कुछ के लिए उपयोगी हो सकता है।

स्थिर स्ट्रिंग एनकोड (स्ट्रिंग s, स्ट्रिंग अनुमति)

https://developer.android.com/reference/android/net/Uri.html#encode(java.lang.String, java.lang.String)



1

हालांकि काफी पुराना है, फिर भी एक त्वरित प्रतिक्रिया:

वसंत उरियटिल्स प्रदान करता है - इसके साथ आप निर्दिष्ट कर सकते हैं कि कैसे एन्कोड किया गया है और यह किस भाग से संबंधित है URI, उदा

encodePathSegment
encodePort
encodeFragment
encodeUriVariables
....

मैं उनका उपयोग करता हूं क्योंकि हम पहले से ही स्प्रिंग का उपयोग कर रहे हैं, अर्थात किसी एडिटोनल लाइब्रेरी की आवश्यकता नहीं है!



0

क्या मैं गलत तरीके का उपयोग कर रहा हूँ? मेरे द्वारा उपयोग की जाने वाली सही विधि क्या है?

हां, यह विधि java.net.URLEncoder.encode को युक्ति ( स्रोत ) के अनुसार "" को "20%" में बदलने के लिए नहीं बनाया गया था ।

अंतरिक्ष चरित्र "" को प्लस चिह्न "+" में परिवर्तित किया जाता है।

यहां तक ​​कि यह सही तरीका नहीं है, आप इसे संशोधित कर सकते हैं: System.out.println(java.net.URLEncoder.encode("Hello World", "UTF-8").replaceAll("\\+", "%20"));एक अच्छा दिन =)।


आप एक ऐसी विधि का उपयोग करने का सुझाव दे रहे हैं जो पर्याप्त नहीं है ( URLEncoder.encode) और इसका उपयोग करके पैच करें replaceAllजो केवल इस विशिष्ट मामले में काम करेगा। इसके बजाय सही वर्ग और पद्धति का उपयोग करें, अन्य उत्तर देखें।
pyb

@pyb ऐसा लगता है कि आप समझ नहीं सकते कि मैंने क्या लिखा है। मैंने कभी नहीं कहा "मैं इसका उपयोग करने का सुझाव देता हूं", मैंने कहा "आप कर सकते हैं"। कृपया लिखने से पहले पढ़ें और समझें।
20

यह एक प्रश्न और उत्तर वेबसाइट है, न कि एक नियमित संदेश बोर्ड जहां लोग चैट करते हैं। यदि आपके पास कोई टिप्पणी है, तो टिप्पणियों का उपयोग करें। लम्बी बात? चैट का उपयोग करें। एक उत्तर के रूप में आप असहमत होने वाले कोड को पोस्ट न करें। दूसरों के योगदान और व्याख्यान देने से पहले कृपया इस साइट के नियमों को पढ़ें और समझें।
pyb

1
मैं इसे वापस बढ़ा रहा हूं क्योंकि अधिकांश अन्य समाधान समान सलाह प्रदान करते हैं। इस पद्धति को गलत साबित करने के लिए कोई "विशिष्ट मामले" प्रदान नहीं किए गए। ट्रैप-कैच ब्लॉक या निर्भरता के साथ अपाचे कॉमन्स का उपयोग करना एक विधि के लिए बहुत अधिक परेशानी है जो कि प्रतिस्थापन के साथ प्रभावी रूप से पैच किया जा सकता है।
यूजीन कार्तोयेव

-2

इस समस्या से निपटने के लिए MyUrlEncode.URLencoding (स्ट्रिंग url, स्ट्रिंग एन्क) का उपयोग करें

    public class MyUrlEncode {
    static BitSet dontNeedEncoding = null;
    static final int caseDiff = ('a' - 'A');
    static {
        dontNeedEncoding = new BitSet(256);
        int i;
        for (i = 'a'; i <= 'z'; i++) {
            dontNeedEncoding.set(i);
        }
        for (i = 'A'; i <= 'Z'; i++) {
            dontNeedEncoding.set(i);
        }
        for (i = '0'; i <= '9'; i++) {
            dontNeedEncoding.set(i);
        }
        dontNeedEncoding.set('-');
        dontNeedEncoding.set('_');
        dontNeedEncoding.set('.');
        dontNeedEncoding.set('*');
        dontNeedEncoding.set('&');
        dontNeedEncoding.set('=');
    }
    public static String char2Unicode(char c) {
        if(dontNeedEncoding.get(c)) {
            return String.valueOf(c);
        }
        StringBuffer resultBuffer = new StringBuffer();
        resultBuffer.append("%");
        char ch = Character.forDigit((c >> 4) & 0xF, 16);
            if (Character.isLetter(ch)) {
            ch -= caseDiff;
        }
        resultBuffer.append(ch);
            ch = Character.forDigit(c & 0xF, 16);
            if (Character.isLetter(ch)) {
            ch -= caseDiff;
        }
         resultBuffer.append(ch);
        return resultBuffer.toString();
    }
    private static String URLEncoding(String url,String enc) throws UnsupportedEncodingException {
        StringBuffer stringBuffer = new StringBuffer();
        if(!dontNeedEncoding.get('/')) {
            dontNeedEncoding.set('/');
        }
        if(!dontNeedEncoding.get(':')) {
            dontNeedEncoding.set(':');
        }
        byte [] buff = url.getBytes(enc);
        for (int i = 0; i < buff.length; i++) {
            stringBuffer.append(char2Unicode((char)buff[i]));
        }
        return stringBuffer.toString();
    }
    private static String URIEncoding(String uri , String enc) throws UnsupportedEncodingException { //对请求参数进行编码
        StringBuffer stringBuffer = new StringBuffer();
        if(dontNeedEncoding.get('/')) {
            dontNeedEncoding.clear('/');
        }
        if(dontNeedEncoding.get(':')) {
            dontNeedEncoding.clear(':');
        }
        byte [] buff = uri.getBytes(enc);
        for (int i = 0; i < buff.length; i++) {
            stringBuffer.append(char2Unicode((char)buff[i]));
        }
        return stringBuffer.toString();
    }

    public static String URLencoding(String url , String enc) throws UnsupportedEncodingException {
        int index = url.indexOf('?');
        StringBuffer result = new StringBuffer();
        if(index == -1) {
            result.append(URLEncoding(url, enc));
        }else {
            result.append(URLEncoding(url.substring(0 , index),enc));
            result.append("?");
            result.append(URIEncoding(url.substring(index+1),enc));
        }
        return result.toString();
    }

}

9
पहिया को फिर से आविष्कार करना, एक कोड-आधार पर सुपर त्रुटि-प्रवण कोड जोड़ना लगभग हमेशा एक बुरा निर्णय है।
क्लिंट ईस्टवुड

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.