2010-09-03 10 views
14

यूनिकोड के विभिन्न एन्कोडिंग में, उदाहरण के लिए यूटीएफ -16le या यूटीएफ -8, एक चरित्र 2 या 3 बाइट्स पर कब्जा कर सकता है। कई यूनिकोड अनुप्रयोग यूनिकोड वर्णों की प्रदर्शन चौड़ाई की देखभाल नहीं करते हैं जैसे कि वे सभी लैटिन अक्षरों हैं। उदाहरण के लिए, -column पाठ में, चाहिए चीनी अक्षरों या एक पंक्ति में लैटिन वर्ण, लेकिन सबसे अधिक आवेदन (ग्रहण, नोटपैड की तरह ++ और सभी प्रसिद्ध पाठ संपादक शामिल है जो, मैं हिम्मत हो, तो कोई अच्छा अपवाद) बस प्रत्येक चीनी चरित्र को लैटिन अक्षर के रूप में 1 चौड़ाई के रूप में गिनें। यह निश्चित रूप से परिणाम प्रारूप बदसूरत और गैर गठबंधन बनाते हैं।यूनिकोड वर्णों की पसंदीदा प्रदर्शन चौड़ाई (कॉलम में) को कैसे जानें?

उदाहरण के लिए, 8 के एक टैब-चौड़ाई निम्नलिखित बदसूरत परिणाम (1 प्रदर्शन चौड़ाई के रूप में सभी यूनिकोड गिनती) मिल जाएगा:

apple 10 
banana 7 
苹果  6 
猕猴桃  31 
pear 16 

हालांकि, उम्मीद प्रारूप है (2 चौड़ाई के रूप में प्रत्येक चीनी चरित्र गणना):

apple 10 
banana 7 
苹果 6 
猕猴桃 31 
pear 16 

वर्ण के प्रदर्शन चौड़ाई पर अनुचित गणना इन संपादकों पूरी तरह से बेकार जब टैब-संरेखण, और पंक्ति लपेटना और पैरा पुनः स्वरूपित कर सकते हैं।

हालांकि, एक चरित्र की चौड़ाई अलग-अलग फ़ॉन्ट्स के बीच भिन्न हो सकती है, लेकिन फिक्स्ड-साइज टर्मिनल फ़ॉन्ट के सभी मामलों में, चीनी चरित्र हमेशा डबल चौड़ाई होता है। ऐसा कहने के लिए, फ़ॉन्ट के बावजूद, प्रत्येक चीनी चरित्र को 2 चौड़ाई में प्रदर्शित करना पसंद किया जाता है।

समाधान में से एक मैं सही चौड़ाई परिवर्तित द्वारा एन्कोडिंग जीबी 2312 को, जीबी 2312 में प्रत्येक चीनी चरित्र एन्कोडिंग 2 बाइट्स लेता है प्राप्त कर सकते हैं, है। हालांकि, कुछ यूनिकोड वर्ण GB2312 वर्णमाला (या GBK वर्णसेट) में मौजूद नहीं हैं। और, सामान्य रूप से बाइट्स में एन्कोडेड आकार से प्रदर्शन चौड़ाई की गणना करना एक अच्छा विचार नहीं है।

यूनिकोड में सभी वर्णों की गणना करने के लिए (\u0080 .. \uFFFF) के रूप में 2 चौड़ाई भी सही नहीं है, क्योंकि सीमा में बिखरे हुए कई 1-चौड़ाई वाले वर्ण भी हैं।

अरबी अक्षरों और कोरियाई अक्षरों की प्रदर्शन चौड़ाई की गणना करते समय भी मुश्किल है, क्योंकि वे यूनिकोड कोड बिंदुओं की मनमानी संख्या से शब्द/चरित्र बनाते हैं।

तो, यूनिकोड कोड बिंदु की डिस्प्ले चौड़ाई शायद एक पूर्णांक नहीं है, मुझे लगता है कि ठीक है, उन्हें अभ्यास में पूर्णांक के लिए ग्राउंड किया जा सकता है, कम से कम किसी से भी बेहतर नहीं।

तो, यूनिकोड मानक में एक char की पसंदीदा प्रदर्शन चौड़ाई से संबंधित कोई विशेषता है? या किसी भी जावा लाइब्रेरी फ़ंक्शन प्रदर्शन चौड़ाई की गणना करने के लिए?

+0

मुझे लगता है कि समस्या यह है कि चौड़ाई फ़ॉन्ट पर निर्भर है, इसलिए आप या तो वर्णों की गणना करते हैं (जिसमें आपको समस्या है), या आप स्ट्रिंग-इन-फ़ॉन्ट लंबाई की गणना करते हैं, और इसका उपयोग करते हैं। –

उत्तर

18

ध्वनि आप wcwidth और wcswidth, IEEE Std 1,003.1-2001 में परिभाषित की तरह कुछ के लिए देख रहे हैं, लेकिन आईएसओ सी से हटा:

wcwidth() समारोह स्तंभ की संख्या का निर्धारण करेगा पदों के लिए आवश्यक विस्तृत चरित्र wcwcwidth() समारोह या तो लौटा देगा 0 (यदि WC एक अशक्त चौड़े चरित्र कोड है), या वापसी स्तंभ पदों की संख्या चौड़े चरित्र कोड WC द्वारा कब्जा किया जा करने के लिए, या वापसी -1 (यदि wc एक प्रिंट करने योग्य विस्तृत-वर्ण कोड के अनुरूप नहीं है)।

मार्कस कुह्न ने यूनिकोड 5.0 के आधार पर एक ओपन सोर्स संस्करण, wcwidth.c लिखा था। यह समस्या का विवरण, और इस क्षेत्र में मानकों की कमी की अभिस्वीकृति में शामिल हैं:

निश्चित-चौड़ाई आउटपुट डिवाइस में, लैटिन वर्णों सभी एक ही "सेल" समान चौड़ाई की स्थिति पर कब्जा है, जबकि आइडियोग्राफ़िक सीजेके पात्र दो ऐसी कोशिकाओं पर कब्जा करते हैं। यूटीएफ -8 एन्कोडिंग का उपयोग करते हुए टर्मिनल-लाइन अनुप्रयोगों और (टेलीटाइप-स्टाइल) वर्ण टर्मिनल के बीच इंटरऑपरेबिलिटी के लिए इस बात की आवश्यकता होती है कि किस चरित्र पर कर्सर को कितनी सेल स्थिति से आगे बढ़ाना चाहिए। कोई स्थापित औपचारिक मानकों वर्तमान में मौजूद है जिस पर यूनिकोड चरित्र चरित्र टर्मिनलों पर कितने सेल पदों पर कब्जा करेगा। यूनिकोड कंसोर्टियम द्वारा प्रदान किए गए डेटा पर लागू सरल नियमों के आधार पर इस तरह के व्यवहार को परिभाषित करने के लिए ये दिनचर्या का पहला प्रयास है। [...]

यह निम्नलिखित नियम लागू करता है:

  • नल केरेक्टर (यू + 0000) 0.
  • अन्य C0/C1 नियंत्रण वर्णों का एक स्तंभ चौड़ाई है और डेल की वापसी को बढ़ावा मिलेगा -1 का मूल्य
  • गैर रिक्ति और संयोजन enclosing वर्ण (सामान्य श्रेणी कोड Mn या मेरे यूनिकोड डेटाबेस में) 0.
  • सॉफ़्ट हाइफ़न (U + 00AD) के एक स्तंभ चौड़ाई है 1.
  • अन्य एक स्तंभ चौड़ाई है प्रारूप वर्ण (यूनिकोड डेटाबेस में सामान्य श्रेणी कोड सीएफ) और शून्य WIDTH स्पेस (यू + 200 बी) की कॉलम चौड़ाई 0.
  • हैंगुल जामो मेडियल स्वर और अंतिम व्यंजन (यू +1160-यू +11 एफएफ) में एक कॉलम है 0.
  • यूनिकोड तकनीकी रिपोर्ट # 11 में परिभाषित पूर्व एशियाई वाइड (डब्ल्यू) या पूर्वी एशियाई पूर्ण-चौड़ाई (एफ) श्रेणी में वर्णों को वर्णित करने के लिए कॉलम चौड़ाई 2.
  • है
  • सभी शेष वर्ण (सभी प्रिंट करने योग्य आईएसओ 8859-1 और WGL4 वर्ण, यूनिकोड नियंत्रण वर्ण, आदि सहित), के 1.
+0

+1 ग्रेट स्पष्टीकरण। हालांकि जावा में 'wcwidth()' फ़ंक्शन नहीं है, लेकिन इसे स्वयं लिखना बहुत आसान है, मार्गदर्शिका का पालन करें। पूर्वी एशियाई चौड़ाई (एन/डब्ल्यू/एच/एफ/ना) पर अधिक जानकारी के लिए @ बॉबन्स का जवाब भी देखें। –

4

आप कोड पॉइंट, ग्रैफेम्स और एन्कोडिंग को भ्रमित कर रहे हैं।

एन्कोडिंग यह है कि भंडारण, संचरण या प्रसंस्करण के लिए कोड बिंदुओं को ऑक्टेट स्ट्रीम में कैसे परिवर्तित किया जाता है। यूटीएफ -8 और यूटीएफ -16 दोनों परिवर्तनीय चौड़ाई एन्कोडिंग हैं, विभिन्न कोड बिंदुओं के साथ अलग-अलग ऑक्टेट्स की आवश्यकता होती है (यूटीएफ -8 के लिए 1 से, आईआईआरसी, 6 और यूटीएफ -16 या तो 2 या 4)।

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

आईई। एक ही ग्रैफेम के एन्कोडिंग की लंबाई एन्कोडिंग और सामान्यीकरण पर निर्भर करेगी।

ग्रैफेम की प्रदर्शन चौड़ाई एन्कोडिंग लंबाई से स्वतंत्र रूप से टाइपफेस, शैली और आकार पर निर्भर करेगी।

अधिक जानकारी के लिए, विकिपीडिया को Unicode और Unicode's home पर देखें। Yannis Haralambous, O'Reilly द्वारा कुछ उत्कृष्ट किताबें भी हैं, शायद सबसे विशेष रूप से "Fonts & Encodings"।

+0

+1। बस एक मामूली टिप्पणी: वैध यूटीएफ -8 एन्कोडेड कोड पॉइंट्स 4 ऑक्टेट तक लेते हैं। –

+0

@ नीमनजा मूल परिभाषा (मूल 31 बिट यूनिवर्सल कैरेक्टर सेट के लिए) या 24 बिट यूनिकोड के लिए रेफिन आरएफसी 3629/यूनिकोड परिभाषा। उत्तरार्द्ध वास्तव में 4 ऑक्टेट तक सीमित है क्योंकि 24 बिट्स के लिए यह आवश्यक है। – Richard

+0

आप सही हैं, लेकिन मैं उलझन में नहीं हूं, हालांकि मैंने शब्दावली का सही ढंग से उपयोग नहीं किया है। आपको बिंदु नहीं मिला, मेरा मतलब है कि निश्चित आकार टर्मिनल फ़ॉन्ट यहां है, और मेरा प्रश्न पसंदीदा प्रदर्शन चौड़ाई के बारे में है, सटीक प्रदर्शन चौड़ाई नहीं। इसमें कोई संदेह नहीं है कि, उदाहरण के लिए, सभी सीजेके पात्र 2 चौड़ाई लेते हैं, मेरा सवाल यह है कि यूनिकोड टर्मिनल विंडो में यूनिकोड को अधिक सही तरीके से संभालने के लिए ऐसी विशेषता देता है या नहीं। कुछ वर्ण (जैसे संयोजन) कई कोड बिंदुओं द्वारा निर्मित किए जाते हैं, इस मामले में, मैं जानना चाहता हूं कि एक स्ट्रिंग से पसंदीदा प्रदर्शन चौड़ाई की गणना करने के लिए परिभाषित फ़ंक्शन है या नहीं। –

3

इस अवधारणा को दर्शाने वाली यूनिकोड संपत्ति East_Asian_Width है। यह सामान्य यूनिकोड प्रतिपादन के संदर्भ में दृश्य चौड़ाई के रूप में वास्तव में विश्वसनीय नहीं है, क्योंकि गैर-एशियाई पात्र, अक्षर संयोजन आदि एक मोनोस्पेस्ड फ़ॉन्ट में भी लाइन में विफल हो जाएंगे। (आपका उदाहरण निश्चित रूप से मेरे लिए रेखांकित नहीं करता है।)

जावा में इस संपत्ति को वर्णों के लिए पढ़ने की अंतर्निहित क्षमता नहीं है (हालांकि Android's extension करता है)। यदि आपको वास्तव में इसकी आवश्यकता है तो आप इसे ICU4J से प्राप्त कर सकते हैं।

+0

यह वही है जो मैं चाहता हूं, और यह प्रॉपर्टी फ़ाइल उपयोगी है: http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt यह भी दिखाता है कि विभिन्न चौड़ाई सभी पर यादृच्छिक रूप से बिखरी हुई है। –

2

एक स्तंभ चौड़ाई मुझे लगता है कि सही ढंग से ऐसा करने के लिए विश्वास है कि आप कि विचार करने की जरूरत प्रकाशित यूनिकोड स्टैंडर्ड के घटक आप पर्ल में प्रोग्रामिंग कर रहे थे, क्या आप जानना चाहते हैं सुपर आसान होगा चाहते हैं, क्योंकि पर्ल के Unicode::LineBreak मॉड्यूल UAX को लागू # 14 हैं के रूप में Unicode Standard Annex #14, the Unicode Line Breaking Algorithm.

में जाना जाता है एक सरल columns विधि के साथ एक वर्ग है जो आपको बताता शामिल इसके स्ट्रिंग तर्क के लिए सही जवाब। ये चीजें एशियाई भाषाओं पर विशेष रूप से अच्छी तरह से काम करती हैं, जहां निरपेक्ष कुछ भी नहीं करेगा। इस मॉड्यूल में 6,000 से अधिक यूनिट परीक्षण शामिल हैं, सक्रिय रूप से बनाए रखा जाता है, और इसका लेखक स्वयं एशियाई है, इसलिए इन मुश्किल बिट्स को बिल्कुल सही करने के लिए उनके लिए यह महत्वपूर्ण है।

मॉड्यूल के अधिकांश गले सी में लिखी एक लाइब्रेरी हैं। मैंने देखा नहीं है कि इसके घटक सी लाइब्रेरी को अन्य भाषाओं से पर्ल पर कैसे कॉल करें, लेकिन आप देख सकते हैं कि यह संभव हो सकता है या नहीं।

1

"या किसी भी जावा लाइब्रेरी फ़ंक्शन को प्रदर्शन चौड़ाई की गणना करने के लिए?": यदि कोई है तो मैंने इसे कभी नहीं मिला है।

किसी चरित्र/स्ट्रिंग की चौड़ाई को कैलुलेट करने का सबसे आसान तरीका यह है कि इसे जीएनयू यूनिकोड फ़ॉन्ट (http://unifoundry.com/unifont.html) & में वर्ण चौड़ाई को मापना है। साफ नहीं है, लेकिन अब तक यह हर एन्कोडिंग के लिए काम किया है जिसके बारे में मैं सोच सकता हूं।

FWIW यहाँ मैं क्या कर रहा है:

java.awt.font.Font MONOSPACEFONT = Font.createFont(Font.TRUETYPE_FONT, 
    new File("unifont-5.1.20080907.ttf")); 

java.awt.font.FontRenderContext FRC = new FontRenderContext(null, true, true); 

int charWidth = (int) (2.0*((java.awt.geom.Rectangle2D.Float) 
    MONOSPACEFONT.getStringBounds(stringToMeasure, FRC)).width); 

... यह बहुत ज्यादा कहीं भी आप अपने JVM तैनात काम करना चाहिए (यह एक बिना सिर के माहौल में ठीक चलता है)।

+0

मैंने कोड का परीक्षण नहीं किया, लेकिन ऐसा लगता है कि चौड़ाई पिक्सल में है, लेकिन कॉलम में नहीं। (मैंने इरादे को दर्शाने के लिए प्रश्न शीर्षक अपडेट किया है) –

+0

नहीं - यह कॉलम है :-) –

संबंधित मुद्दे