जावा में एक "सरोगेट जोड़ी" क्या है?


149

मैं StringBufferविशेष रूप से रिवर्स () विधि के लिए प्रलेखन पढ़ रहा था । उस प्रलेखन में सरोगेट जोड़े के बारे में कुछ उल्लेख किया गया है । इस संदर्भ में सरोगेट जोड़ी क्या है? और निम्न और उच्च सरोगेट क्या हैं ?


3
यह UTF-16 शब्दावली है, यहाँ समझाया गया है: download.oracle.com/javase/6/docs/api/java/lang/…
wkl

1
यह विधि छोटी गाड़ी है: इसमें पूर्ण वर्ण - कोड बिंदुओं को उल्टा करना चाहिए - इनके अलग-अलग टुकड़े नहीं ,: कोड इकाइयाँ। बग यह है कि विशेष रूप से विरासत विधि कोड बिंदुओं के बजाय केवल व्यक्तिगत चार इकाइयों पर काम करती है, जो कि आप चाहते हैं किString यह केवल चार इकाइयों से बना हो। बहुत बुरा जावा आपको इसे ठीक करने के लिए OO का उपयोग करने की अनुमति नहीं देता है, लेकिन Stringवर्ग और वर्ग दोनों StringBufferको finalized किया गया है । कहो, क्या यह हत्या के लिए एक व्यंजना नहीं है? :)
tchrist

2
@tchrist प्रलेखन (और स्रोत) का कहना है कि यह कोड बिंदुओं की एक स्ट्रिंग के रूप में रिवर्स करता है। (संभवतः 1.0.2 ने ऐसा नहीं किया, और आपको इन दिनों ऐसा व्यवहार कभी नहीं मिलेगा।)
टॉम हॉल्टिन -

जवाबों:


127

शब्द "सरोगेट पेयर" यूटीएफ -16 एन्कोडिंग योजना में उच्च कोड-पॉइंट्स के साथ यूनिकोड वर्णों को एन्कोड करने का एक साधन है।

यूनिकोड वर्ण एन्कोडिंग में, वर्णों को 0x0 और 0x10FFFF के बीच मानों में मैप किया जाता है।

आंतरिक रूप से, जावा यूटीएफ -16 एन्कोडिंग योजना का उपयोग यूनिकोड पाठ के तार को संग्रहीत करने के लिए करता है। UTF-16 में, 16-बिट (दो-बाइट) कोड इकाइयों का उपयोग किया जाता है। चूंकि 16 बिट में केवल 0x0 से 0xFFFF तक वर्णों की श्रेणी हो सकती है, इस सीमा से ऊपर मूल्यों को संग्रहीत करने के लिए कुछ अतिरिक्त जटिलता का उपयोग किया जाता है (0x10000 से 0x10FFFF)। यह सरोगेट्स के रूप में जानी जाने वाली कोड इकाइयों के जोड़े का उपयोग करके किया जाता है।

सरोगेट कोड इकाइयां दो श्रेणियों में "उच्च सरोगेट" और "कम सरोगेट" के रूप में जानी जाती हैं, यह इस बात पर निर्भर करता है कि उन्हें दो-कोड-यूनिट अनुक्रम के प्रारंभ या अंत में अनुमति दी गई है।


4
इसमें सबसे अधिक वोट हैं, फिर भी यह एक भी कोड उदाहरण नहीं देता है। और न ही इन जवाबों में से कोई भी वास्तव में इसका उपयोग कैसे करें। इसीलिए इसे डाउनवोट किया जा रहा है।
जॉर्ज जेवियर

57

प्रारंभिक जावा संस्करणों ने 16-बिट चार डेटा प्रकार का उपयोग करके यूनिकोड वर्णों का प्रतिनिधित्व किया। इस डिजाइन ने उस समय समझ में आया, क्योंकि सभी यूनिकोड वर्णों में 65,535 (0xFFFF) से कम मूल्य थे और 16 बिट्स में प्रतिनिधित्व किया जा सकता था। हालांकि, बाद में, यूनिकोड ने अधिकतम मूल्य 1,114,111 (0x10FFFF) तक बढ़ा दिया। क्योंकि यूनिकोड संस्करण 3.1 में सभी यूनिकोड वर्णों का प्रतिनिधित्व करने के लिए 16-बिट मान बहुत छोटे थे, लेकिन यूटीएफ -32 एन्कोडिंग योजना के लिए 32-बिट मानों को कोड पॉइंट कहा जाता है। लेकिन कुशल मेमोरी उपयोग के लिए 32-बिट मानों पर 16-बिट मान पसंद किए जाते हैं, इसलिए यूनिकोड ने 16-बिट मूल्यों के निरंतर उपयोग की अनुमति देने के लिए एक नया डिज़ाइन पेश किया। UTF-16 एन्कोडिंग योजना में अपनाई गई यह डिज़ाइन 1,024 मानों को 16-बिट उच्च सरोगेट (रेंज U + D800 से U + DBFF) में और अन्य 1,024 मानों को 16-बिट कम किराए (रेंज U + DC00 में) प्रदान करती है से यू + डीएफएफएफ)।


7
मुझे यह स्वीकार किए गए उत्तर से बेहतर लगता है, क्योंकि यह बताता है कि कैसे यूनिकोड 3.1 ने 1024 * 1024 नए मूल्यों को हासिल करने के लिए मूल 65535 में से 1024 + 1024 (उच्च + निम्न) मानों को जोड़ा, जिनकी कोई आवश्यकता नहीं है, जो कि पार्सर्स की शुरुआत में शुरू होते हैं। स्ट्रिंग।
एरिक हिस्ट

1
मुझे यह जवाब पसंद नहीं है कि यूटीएफ -16 लगाने का यह सबसे स्मृति-कुशल यूनिकोड एन्कोडिंग है। UTF-8 मौजूद है, और अधिकांश पाठ को दो बाइट्स के रूप में प्रस्तुत नहीं करता है । UTF-16 का उपयोग आज ज्यादातर किया जाता है क्योंकि Microsoft ने UTF-32 से पहले इसे चुना था, यह मेमोरी दक्षता के लिए नहीं था। केवल उस समय के बारे में जब आप UTF-16 चाहते हैं , जब आप Windows पर बहुत अधिक फ़ाइल हैंडलिंग कर रहे हों, और इसलिए इसे बहुत पढ़ना और लिखना दोनों हैं । अन्यथा, उच्च गति के लिए UTF-32 (b / c निरंतर ऑफसेट) या UTF-8 कम मेमोरी (b / c न्यूनतम 1 बाइट) के लिए
फंड मोनिका का मुकदमा

23

वह दस्तावेज़ जो कह रहा है कि अमान्य UTF-16 स्ट्रिंग्स reverseविधि को कॉल करने के बाद मान्य हो सकता है क्योंकि वे मान्य स्ट्रिंग्स के उलट हो सकते हैं। एक सरोगेट जोड़ी ( यहां चर्चा की गई ) यूटीएफ -16 में 16-बिट मानों की एक जोड़ी है जो एक एकल यूनिकोड कोड बिंदु को एनकोड करती है; निम्न और उच्च सरोगेट उस एन्कोडिंग के दो हिस्से हैं।


6
स्पष्टीकरण। एक स्ट्रिंग को "सही" अक्षर (उर्फ "अंगूर" या "पाठ तत्व") पर उलट देना चाहिए। एक एकल "वर्ण" कोड बिंदु एक या दो "चार" वर्ण (सरोगेट जोड़ी) हो सकता है, और एक अंगूर उन कोड बिंदुओं में से एक या एक से अधिक हो सकता है (अर्थात एक आधार वर्ण कोड प्लस एक या एक से अधिक संयोजन वर्ण, जिनमें से प्रत्येक एक या दो 16-बिट विखंडू या "वर्ण" लंबे) हो सकते हैं। इसलिए एक एकल ग्रैफेम प्रत्येक दो "वर्ण" लंबे, कुल मिलाकर 6 "वर्ण" तीन वर्ण हो सकता है। सभी 6 "वर्ण" को एक साथ रखा जाना चाहिए, क्रम में (अर्थात उलट नहीं), जब वर्णों के पूरे स्ट्रिंग को उलट दिया जाता है।
त्रिनको

4
इसलिए "चार" डेटा प्रकार भ्रामक है। "वर्ण" एक ढीला शब्द है। "चार" प्रकार वास्तव में सिर्फ UTF16 चंक आकार है और हम इसे सरोगेट जोड़े की सापेक्ष दुर्लभता के कारण चरित्र कहते हैं (अर्थात यह आमतौर पर एक पूरे वर्ण कोड बिंदु का प्रतिनिधित्व करता है), इसलिए "वर्ण" वास्तव में एक एकल कोड कोड बिंदु को संदर्भित करता है , लेकिन फिर संयोजन पात्रों के साथ, आपके पास ऐसे पात्रों का एक क्रम हो सकता है जो एकल "वर्ण / ग्रैपहेम / पाठ तत्व" के रूप में प्रदर्शित होते हैं। यह रॉकेट साइंस नहीं है; अवधारणाएँ सरल हैं, लेकिन भाषा भ्रामक है।
त्रिनको

जिस समय जावा का विकास हो रहा था, उस समय यूनिकोड शैशवावस्था में था। यूनिकोड को सरोगेट जोड़े मिलने से पहले जावा लगभग 5 वर्षों के लिए था, इसलिए उस समय 16-बिट चार फिट काफी अच्छा था। अब, आप UTF-16 की तुलना में UTF-8 और UTF-32 का उपयोग करना बेहतर समझते हैं।
जोनाथन बाल्डविन

23

इस पोस्ट से उपरोक्त उत्तर के लिए कुछ और जानकारी जोड़ना ।

जावा -12 में परीक्षण, 5 से ऊपर सभी जावा संस्करणों में काम करना चाहिए।

जैसा कि यहाँ उल्लेख किया गया है: https://stackoverflow.com/a/47505451/2987755 ,
जो भी चरित्र (यूनिकोड U + FFFF से ऊपर है) को एक सरोगेट जोड़ी के रूप में दर्शाया गया है, जो जावा को चार मानों की एक जोड़ी के रूप में संग्रहीत करता है, अर्थात एकल यूनिकोड चरित्र को दो आसन्न जावा वर्णों के रूप में दर्शाया गया है।
जैसा कि हम निम्नलिखित उदाहरण में देख सकते हैं।
1. लंबाई:

"🌉".length()  //2, Expectations was it should return 1

"🌉".codePointCount(0,"🌉".length())  //1, To get the number of Unicode characters in a Java String  

2. समानता: नीचे के रूप में
यूनिकोड का उपयोग करते हुए स्ट्रिंग के लिए "" "का प्रतिनिधित्व \ud83c\udf09करें और समानता की जांच करें।

"🌉".equals("\ud83c\udf09") // true

जावा UTF-32 का समर्थन नहीं करता है

"🌉".equals("\u1F309") // false  

3. आप यूनिकोड चरित्र को जावा स्ट्रिंग में परिवर्तित कर सकते हैं

"🌉".equals(new String(Character.toChars(0x0001F309))) //true

4. String.substring () पूरक वर्णों पर विचार नहीं करता है

"🌉🌐".substring(0,1) //"?"
"🌉🌐".substring(0,2) //"🌉"
"🌉🌐".substring(0,4) //"🌉🌐"

इसे हल करने के लिए हम उपयोग कर सकते हैं String.offsetByCodePoints(int index, int codePointOffset)

"🌉🌐".substring(0,"🌉🌐".offsetByCodePoints(0,1) // "🌉"
"🌉🌐".substring(2,"🌉🌐".offsetByCodePoints(1,2)) // "🌐"

5. ब्रेकइंटरेटर के साथ यूनिकोड स्ट्रिंग को बदलना
6. यूनिकोड java.text.Collator के साथ स्ट्रिंग्स को सॉर्ट करना
। वर्ण। toUpperCase()( toLowerCase(), विधियों का उपयोग नहीं किया जाना चाहिए, इसके बजाय, स्ट्रिंग अपरकेस और विशेष रूप से लोअरकेस का उपयोग करें।
8. Character.isLetter(char ch)समर्थन नहीं करता है, बेहतर उपयोग किया जाता है Character.isLetter(int codePoint), methodName(char ch)चरित्र वर्ग में प्रत्येक विधि के लिए प्रकार होगा methodName(int codePoint)जो पूरक वर्णों को संभाल सकता है।
9. String.getBytes()बाइट्स से स्ट्रिंग में परिवर्तित करना InputStreamReader,OutputStreamWriter

रेफरी:
https://coolsymbol.com/emojis/emoji-for-copy-and-paste.html#objects
https://www.online-toolz.com/tools/text-unicode-entities-convertor.pht
https: //www.ibm.com/developerworks/library/j-unicode/index.html
https://www.oracle.com/technetwork/articles/javaee/supplementary-142654.html

उदाहरण के लिए अधिक जानकारी image1 image2
तलाशने लायक अन्य शब्द: सामान्यीकरण , बीड़ी


2
इस उत्तर के लिए वोट करने के लिए विशेष रूप से साइन इन किया गया (मेरा मतलब है कि विंडो को गुप्त से बदलकर सामान्य एक: पी) कर दिया गया है। एक noob के लिए सबसे अच्छा स्पष्टीकरण
एन-जोय

1
धन्यवाद !, मुझे खुशी है कि इसने मदद की, लेकिन मूल पोस्ट लेखक सभी प्रशंसा के हकदार हैं।
dkb

महान उदाहरण! मैंने इसे भी उभारने के लिए लॉग इन किया :) और फिर से, इसने मुझे (फिर से) सोचने पर मजबूर कर दिया कि मैं वास्तव में यह नहीं समझता कि जावा अपने कोड में जीवित कीड़े क्यों रखता है। मैं पूरी तरह से सम्मान करता हूं कि वे मौजूदा कोड को तोड़ना नहीं चाहते हैं, लेकिन चलो ... इन बगों के आसपास काम करने में कितने घंटे खो गए हैं? यदि यह टूट गया है, तो इसे ठीक करें, अरे!
फ्रांज डी।

6

सरोगेट जोड़े कुछ वर्णों को कूटने के लिए UTF-16 के तरीके का उल्लेख करते हैं, http://en.wikipedia.org/wiki/UTF-16/UCS-2#Code_points_U.2B10000..U.2B10FFFF देखें


11
"वर्ण" एक ऐसा भरा हुआ शब्द है।
त्रिकोको

1
यूनिकोड में कोई वर्ण नहीं हैं, लेकिन कोडपॉइंट हैं। प्रत्येक कोडपॉइंट शून्य से कई वर्णों तक प्रस्तुत कर सकता है।
निक वोल्किन

6

छोटा सा प्रस्तावना

  • यूनिकोड कोड बिंदुओं का प्रतिनिधित्व करता है। प्रत्येक कोड बिंदु को यूनिकोड मानक के अनुसार 8-, 16, या 32-बिट ब्लॉक में एन्कोड किया जा सकता है।
  • संस्करण 3.1 से पहले, ज्यादातर उपयोग 8-बिट एनकोडिंग था, जिसे यूटीएफ -8 के रूप में जाना जाता था, और 16-बिट एन्कोडिंग, जिसे यूसीएस -2 या "यूनिवर्सल कैरेक्टर सेट 2 ऑक्टेट्स में कोडित" के रूप में जाना जाता है। यूटीएफ -8 यूनिकोड को 1-बाइट ब्लॉक के अनुक्रम के रूप में बताता है, जबकि यूसीएस -2 हमेशा 2 बाइट लेता है:

    A = 41 - UTF-8
    A = 0041 के साथ 8-बिट्स का एक ब्लॉक - UCS-2
    CS = CE A9 के साथ 16-बिट्स का एक ब्लॉक - UTF-8
    blocks = 03A9 के साथ 8-बिट्स के दो ब्लॉक - एक ब्लॉक यूसीएस -2 के साथ 16-बिट्स

संकट

संघ ने सोचा कि 16 बिट्स किसी भी मानव-पठनीय भाषा को कवर करने के लिए पर्याप्त होंगे, जो 2 ^ 16 = 65536 संभावित कोड मान देता है। यह प्लेन 0 के लिए सच था, जिसे BPM या बेसिक मल्टीलिंगुअल प्लेन के रूप में भी जाना जाता है, जिसमें आज 65536 कोड अंकों में से 55,445 शामिल हैं। BPM चीनी, जापानी-कोरियाई प्रतीकों (CJK) सहित दुनिया की लगभग हर मानव भाषा को शामिल करता है।

समय बीत गया और नए एशियाई चरित्र सेट जोड़े गए, चीनी प्रतीकों ने अकेले 70,000 से अधिक अंक ले लिए। अब, मानक of के हिस्से के रूप में इमोजी अंक भी हैं । नए 16 "अतिरिक्त" प्लान जोड़े गए। UCS-2 कमरा प्लेन -० से बड़ा कुछ भी कवर करने के लिए पर्याप्त नहीं था।

यूनिकोड निर्णय

  1. यूनिकोड को 17 विमान × 65 536 वर्ण प्रति विमान = 1 114 112 अधिकतम बिंदुओं तक सीमित करें।
  2. वर्तमान यूटीएफ -32, जिसे यूसीएस -4 के रूप में जाना जाता है, प्रत्येक कोड बिंदु के लिए 32-बिट्स रखने और सभी विमानों को कवर करने के लिए।
  3. UTF-8 को डायनामिक एन्कोडिंग के रूप में उपयोग करना जारी रखें, प्रत्येक कोड बिंदु के लिए UTF-8 से 4 बाइट अधिकतम करें, अर्थात प्रति बिंदु 1 से 4 बाइट तक।
  4. UCS-2 को डिप्रेस करें
  5. UCS-2 के आधार पर UTF-16 बनाएँ। UTF-16 को गतिशील बनाएं, इसलिए इसमें प्रति पॉइंट 2 बाइट्स या 4 बाइट्स लगते हैं। UTF-16 में 1024 अंक U + D800 – U + DBFF, जिसे हाई सरोगेट्स कहते हैं, असाइन करें; 1024 प्रतीकों को U + DC00-U + DFFF, UTF-16 को लो सरोगेट्स कहते हैं।

    उन परिवर्तनों के साथ, बीपीएम यूटीएफ -16 में 16 बिट्स के 1 ब्लॉक के साथ कवर किया गया है, जबकि सभी "सप्लीमेंटरी कैरेक्टर" को 16 बिट्स द्वारा 2 ब्लॉक पेश करते हुए सरोगेट जोड़े के साथ कवर किया गया है, पूरी तरह से 1024x1024 = 1 048 576 अंक।

    एक उच्च सरोगेट कम सरोगेट से पहले होता है । इस नियम से किसी भी विचलन को खराब एन्कोडिंग माना जाता है। उदाहरण के लिए, एक जोड़े के बिना एक सरोगेट गलत है, एक उच्च सरोगेट से पहले कम सरोगेट गलत है।

    𝄞, 'संगीत प्रतीक जी कुंजी', UTF-16 में किराए की कोख 0xD834 0xDD1E (2 2 से बाइट्स) की एक जोड़ी, के रूप में एन्कोड किया गया है
    0xF0 0x9D 0x84 0x9E (4 से 1 बाइट) के रूप में UTF-8 में,
    के रूप में UTF-32 में 0x0001D11E (4 बाइट्स से 1)।

वर्तमान स्थिति

  • हालांकि मानक के अनुसार सरोगेट विशेष रूप से केवल यूटीएफ -16 को सौंपा जाता है, ऐतिहासिक रूप से कुछ विंडोज और जावा अनुप्रयोगों में यूटीएफ -8 और यूसीएस -2 अंक का उपयोग किया जाता है जो अब सरोगेट रेंज में आरक्षित हैं।
    गलत UTF-8 / UTF-16 एन्कोडिंग के साथ विरासत अनुप्रयोगों का समर्थन करने के लिए, एक नया मानक WTF-8 , Wobbly परिवर्तन प्रारूप बनाया गया था। यह गैर-युग्मित सरोगेट या गलत अनुक्रम जैसे मनमाने सरोगेट बिंदुओं का समर्थन करता है। आज, कुछ उत्पाद मानक का अनुपालन नहीं करते हैं और UTF-8 को WTF-8 मानते हैं।
  • सरोगेट समाधान ने विभिन्न एन्कोडिंग के बीच रूपांतरण में कई सुरक्षा समस्याएं खोलीं , उनमें से ज्यादातर को अच्छी तरह से संभाला गया था।

कई ऐतिहासिक विवरणों को details विषय का पालन करने के लिए दबा दिया गया था।
नवीनतम यूनिकोड मानक http://www.unicode.org/versions/latest पर पाया जा सकता है


3

UTF-16 में एक सरोगेट जोड़ी दो 'कोड इकाइयाँ' हैं जो एक 'कोड पॉइंट' बनाती हैं। जावा प्रलेखन यह कह रहा है कि ये 'कोड पॉइंट' अभी भी मान्य होंगे, रिवर्स के बाद उनकी 'कोड इकाइयाँ' सही ढंग से ऑर्डर की गई हैं। इसमें आगे कहा गया है कि दो अनपेक्षित सरोगेट कोड इकाइयाँ उलट सकती हैं और एक वैध सरोगेट जोड़ी बना सकती हैं। जिसका अर्थ है कि यदि अनपेक्षित कोड इकाइयाँ हैं, तो एक मौका है कि रिवर्स के विपरीत समान नहीं हो सकता है!

ध्यान दें, हालाँकि, दस्तावेज़ीकरण ग्रैफेम्स के बारे में कुछ भी नहीं कहता है - जो कि कई कोडप्वाइंट संयुक्त हैं। जिसका अर्थ ई है और इसके साथ जाने वाला उच्चारण अभी भी स्विच किया जा सकता है, इस प्रकार उच्चारण को ई से पहले रखा जा सकता है। जिसका अर्थ है कि यदि ई से पहले कोई और स्वर है तो उसे वह उच्चारण मिल सकता है जो ई पर था।

ओह!

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