2013-02-25 61 views
5

मुझे पता है कि आप Rebol 2 में^(एफएफ) से बड़े कोडपॉइंट्स के लिए तारों में भागने वाली देखभाल शैली का उपयोग नहीं कर सकते हैं, क्योंकि यह यूनिकोड के बारे में कुछ भी नहीं जानता है। तो यह कुछ भी उत्पन्न नहीं करता है अच्छा है, यह में गड़बड़ लग:रीबोल 2 में रीबोल 3 तारों में यू + एफएफएफएफ के ऊपर यूनिकोड कोडपॉइंट्स का उपयोग कैसे करें?

print {Q: What does a Zen master's {Cow} Say? A: "^(03BC)"!} 

फिर भी कोड REBOL 3 में काम करता है और बाहर प्रिंट:

Q: What does a Zen master's {Cow} Say? A: "μ"! 

बहुत बढ़िया है, लेकिन R3 पकड़ करने की क्षमता बाहर maxes बिल्कुल U + FFFF जाहिरा तौर पर एक तार में एक चरित्र:

>> type? "^(FFFF)" 
== string! 

>> type? "^(010000)" 
** Syntax error: invalid "string" -- {"^^(010000)"} 
** Near: (line 1) type? "^(010000)" 

स्थिति एक बहुत REBOL 2 के यादृच्छिक व्यवहार की तुलना में बेहतर है, जब यह कोड पॉइंट्स इसके बारे में पता नहीं था से मुलाकात की है। हालांकि, अगर आप जानते थे कि अपने यूटीएफ -8 एन्कोडिंग को कैसे करना है (या डिस्क से स्रोत कोड लोड करने के तरीके से आपके तार मिलते हैं) तो स्ट्रिंग को स्टोर करने के लिए रेबोल में एक वर्कअराउंड होता था। आप उन्हें अलग-अलग पात्रों से इकट्ठा कर सकते हैं।

तो UTF-8 U + 010,000 की एन्कोडिंग # F0908080 है, और इससे पहले कि आप कह सकते हैं:

workaround: rejoin [#"^(F0)" #"^(90)" #"^(80)" #"^(80)"] 

और आप उस एकल का उपयोग कर इनकोडिंग कोडपॉइंट साथ एक स्ट्रिंग प्राप्त होता UTF-8, आपको लगता है कि कोड ब्लॉक में डिस्क पर सहेज सकता है और फिर से वापस पढ़ सकता है। क्या आर 3 में कोई समान चाल है?

उत्तर

3

हां, एक चाल है ... जो चाल है जिसे आप आर 2 में भी इस्तेमाल कर रहे थे। एक स्ट्रिंग का उपयोग न करें! एक बाइनरी का प्रयोग करें!

अच्छे वैकल्पिक हल:: आप बात की इस तरह करना है, तो # {F0908080}

यह Rebol2 में काम किया है होता है और यह Rebol3 में काम करता है। आप इसे सहेज सकते हैं और बिना किसी हास्यास्पद व्यवसाय के लोड कर सकते हैं।

वास्तव में, अगर यूनिकोड के बारे में परवाह है, तो ... स्ट्रिंग प्रोसेसिंग करना बंद करें जो कि^(7 एफ) से अधिक कोडपॉइंट्स का उपयोग कर रहा है यदि आप रीबोल 2 में फंस गए हैं और 3 नहीं हैं।

भयानक-वैकल्पिक हल:: पुन: शामिल [# "^ (F0)" # "^ (90)" # "^ (80)" # "^ (80 हम उस भयानक वैकल्पिक हल को देखकर क्यों देखेंगे) "]

... " और आप उस एकल UTF-8 कोडपॉइंट " साथ एक स्ट्रिंग प्राप्त होगी ...

केवल बात आप मिलना चाहिए चार के साथ एक स्ट्रिंग है व्यक्तिगत चरित्र कोडपॉइंट्स, और 4 = length? terrible-workaround के साथ। Rebol2 टूट गया है क्योंकि स्ट्रिंग! मूल रूप से बाइनरी से अलग नहीं है! हुड के नीचे। असल में, Rebol2 में आप दो प्रतिलिपि बनाकर प्रतिलिपि बना सकते हैं, एएस-बिनरी और एएस-STRING देखें। (यह वास्तव में भिन्न है क्योंकि वे वास्तव में अलग हैं, इसलिए सुविधा से जुड़ा न हो!)

इन तारों को 4 की लंबाई की रिपोर्ट करने के लिए कुछ भ्रामक है, और प्रत्येक चरित्र का उत्पादन करने का झूठा आराम है यदि आप उन्हें to integer! रूपांतरित करते हैं तो वही मान। क्योंकि अगर आप उन्हें किसी फ़ाइल या बंदरगाह पर कहीं भी लिखते हैं, और उन्हें एन्कोड करने की आवश्यकता है, तो आप काट लेंगे।Rebol2 में इस नोट:

>> to integer! #"^(80)" 
== 128 

>> to binary! #"^(80)" 
== #{80} 

लेकिन R3 में, आप एक UTF-8 एन्कोडिंग है जब द्विआधारी रूपांतरण की जरूरत है:

>> to integer! #"^(80)" 
== 128 

>> to binary! #"^(80)" 
== #{C280} 

तो तुम एक आश्चर्य है जब आपके प्रतीत होता है-काम कर कोड के लिए में हो जाएगा बाद में कुछ अलग करता है, और हवाओं को अलग-अलग क्रमबद्ध करता है। असल में, अगर आप जानना चाहते हैं कि आर 2 इस संबंध में "गड़बड़" कैसे है, तो देखें कि आपको अपने "एमयू" के लिए अजीब प्रतीक क्यों मिला। आर 2 में:

>> to binary! #"^(03BC)" 
== #{BC} 

यह सिर्फ "03" दूर फेंक दिया। : -:

mu-utf8: #{03BC} 
utf8: rejoin [#{} {Q: What does a Zen master's {Cow} Say? A: "} mu-utf8 {"!}] 

आप एक द्विआधारी हो जाता है यही कारण है कि/

तो अगर आप किसी कारण एक यूनिकोड तार के साथ काम करने के लिए की जरूरत है और R3 परिवर्तन नहीं कर सकते, गाय उदाहरण के लिए कुछ इस तरह की कोशिश करो। इसे डीबग आउटपुट के लिए केवल स्ट्रिंग में कनवर्ट करें, और गंदगी देखने के लिए तैयार रहें। लेकिन अगर आप Rebol2 में फंस गए हैं तो यह सही काम है।

और जवाब दोहराते हैं:

utf8: rejoin [#{} {Q: What did the Mycenaean's {Cow} Say? A: "} #{010000} {"!}] 

मुझे यकीन है कि अगर मैं एक बहुत ही अजीब मजाक होगा हूँ: यह भी अगर कुछ अजीब अटक कारण Rebol3 में उन उच्च कोड पॉइंट्स का उपयोग करने की आवश्यकता होगी, के लिए क्या करना है पता था कि LINEAR B SYLLABLE B008 A क्या था। जो मुझे यह कहने के लिए प्रेरित करता है कि सबसे अधिक संभावना है, यदि आप कुछ कर रहे हैं तो यह गूढ़ आपके पास उदाहरण के रूप में केवल कुछ कोडपॉइंट्स उद्धृत किए जा रहे हैं। जब तक आपको उन्हें आसानी से स्लॉट करने की आवश्यकता नहीं होती है, तब तक आप अपने अधिकांश डेटा को स्ट्रिंग के रूप में पकड़ सकते हैं, और परिणाम को बाइनरी श्रृंखला में रख सकते हैं।


अद्यतन: एक इस समस्या को मारता है, यहाँ एक उपयोगिता समारोह है कि यह चारों ओर अस्थायी रूप से काम करने के लिए उपयोगी हो सकता है है:, आप एक to binary! रूपांतरण के बजाय इस का उपयोग करते हैं

safe-r2-char: charset [#"^(00)" - #"^(7F)"] 
unsafe-r2-char: charset [#"^(80)" - #"^(FF)"] 
hex-digit: charset [#"0" - #"9" #"A" - #"F" #"a" - #"f"] 

r2-string-to-binary: func [ 
    str [string!] /string /unescape /unsafe 
    /local result s e escape-rule unsafe-rule safe-rule rule 
] [ 
    result: copy either string [{}] [#{}] 
    escape-rule: [ 
     "^^(" s: 2 hex-digit e: ")" (
      append result debase/base copy/part s e 16 
     ) 
    ] 
    unsafe-rule: [ 
     s: unsafe-r2-char (
      append result to integer! first s 
     ) 
    ] 
    safe-rule: [ 
     s: safe-r2-char (append result first s) 
    ] 
    rule: compose/deep [ 
     any [ 
      (either unescape [[escape-rule |]] []) 
      safe-rule 
      (either unsafe [[| unsafe-rule]] []) 
     ] 
    ] 
    unless parse/all str rule [ 
     print "Unsafe codepoints found in string! by r2-string-to-binary" 
     print "See http://stackoverflow.com/questions/15077974/" 
     print mold str 
     throw "Bad codepoint found by r2-string-to-binary" 
    ] 
    result 
] 

आप Rebol2 और Rebol3 दोनों में लगातार व्यवहार प्राप्त होगा। (इसे प्रभावी ढंग से terrible-workaround शैली तार के लिए एक समाधान लागू करता है।)

3

वहाँ स्ट्रिंग का उपयोग एक समाधान है! डेटाटाइप भी। आप उस मामले में UTF-8 उपयोग नहीं कर सकते, लेकिन इस प्रकार आप UTF-16 तरीके का उपयोग कर सकते हैं:

utf-16: "^(d800)^(dc00)" 

, जो^(10000) कोड UTF-16 के किराए की जोड़ी का उपयोग कर बिंदु encodes।

utf-16: func [ 
    code [integer!] 
    /local low high 
] [ 
    case [ 
     code < 0 [do make error! "invalid code"] 
     code < 65536 [append copy "" to char! code] 
     code < 1114112 [ 
      code: code - 65536 
      low: code and 1023 
      high: code - low/1024 
      append append copy "" to char! high + 55296 to char! low + 56320 
     ] 
     'else [do make error! "invalid code"] 
    ] 
] 
: सामान्य तौर पर, निम्नलिखित समारोह एन्कोडिंग कर सकते हैं