चारसेट नाम स्थिरांक क्यों नहीं हैं?


211

चारसेट मुद्दे स्वयं भ्रमित और जटिल हैं, लेकिन इसके शीर्ष पर आपको अपने वर्णमाला के सटीक नाम याद रखने होंगे। क्या यह है "utf8"? या "utf-8"? या हो सकता है "UTF-8"? कोड नमूनों के लिए इंटरनेट खोजते समय आपको उपरोक्त सभी दिखाई देंगे। क्यों न केवल उन्हें स्थिरांक और उपयोग नाम दिया जाए Charset.UTF8?


19
+1: यह मुझे हर समय परेशान कर रहा था। वैसे ही कहानी आगे MessageDigest#getInstance()बढ़ती है।
बालुसक

2
असली उत्तर के लिए, आपको सूर्य से किसी से पूछना होगा। उस के साथ अच्छी किस्मत :-)
स्टीफन सी

1
स्टीफन सी: मेरा मानना ​​है कि यह एक सार्वजनिक मेलिंग सूची पर चर्चा की गई है। -सोमोन पर सूर्य।
टॉम हॉकिन -

जवाबों:


160

पूछे जाने वाले प्रश्न का सरल उत्तर यह है कि उपलब्ध चार्ट स्ट्रिंग्स प्लेटफ़ॉर्म से प्लेटफ़ॉर्म पर भिन्न होती है।

हालांकि, ऐसे छह हैं जो मौजूद होने के लिए आवश्यक हैं, इसलिए उन लोगों के लिए बहुत पहले ही स्थिरांक बनाए जा सकते थे। मैं नहीं जानता कि वे क्यों नहीं थे।

JDK 1.4 ने चारसेट टाइप को पेश करके एक शानदार काम किया। इस समय, वे स्ट्रिंग स्थिरांक प्रदान नहीं करना चाहते थे, क्योंकि लक्ष्य को चारसेट इंस्टेंसेस का उपयोग करके सभी को प्राप्त करना है। तो छह मानक चारसेट स्थिरांक क्यों नहीं प्रदान करें? मैंने मार्टिन बुचोलज़ से पूछा कि क्या वह मेरे ठीक बगल में बैठा हुआ है, और उन्होंने कहा कि वास्तव में कोई बहुत बड़ा कारण नहीं था, सिवाय इसके कि उस समय, चीजें अभी भी आधी-अधूरी थीं - बहुत कम JDK APIs को वापस कर दिया गया था चारसेट को स्वीकार करें, और जो थे, उनमें से चारसेट ओवरलोड ने आमतौर पर थोड़ा खराब प्रदर्शन किया।

यह दुख की बात है कि यह केवल JDK 1.6 में है कि उन्होंने आखिरकार सबसेट ओवरलोड के साथ सब कुछ समाप्त कर दिया। और यह कि यह पश्चगामी प्रदर्शन की स्थिति अभी भी मौजूद है (यही कारण है कि यह अविश्वसनीय रूप से अजीब है और मैं इसे समझा नहीं सकता, लेकिन सुरक्षा से संबंधित है)।

लंबी कहानी छोटी - बस अपने स्वयं के स्थिरांक को परिभाषित करें, या अमरूद के चार्ट्स वर्ग का उपयोग करें जो टोनी द पोनी से जुड़ा हुआ है (हालांकि वह पुस्तकालय वास्तव में अभी तक जारी नहीं हुआ है)।

अपडेट: एक StandardCharsetsवर्ग JDK 7 में है।


बस जिज्ञासु, किसी भी विचार जब अमरूद की एक रिलीज (अल्फा / बीटा / जो भी हो) होगी? इस पर प्रोजेक्ट होमपेज थोड़ा कर्व है।
जोनीक

मेरे लिए कोई टर्की नहीं है यह बाहर है!
केविन बोर्रिलियन

अविश्वसनीय रूप से अजीब होने का कारण और मैं इसे समझा नहीं सकता, लेकिन सुरक्षा से संबंधित है - आप कस्टम वर्णकों के माध्यम से एक परिवर्तनीय स्ट्रिंग बना सकते हैं, फिर भी उन्हें स्ट्रिंग की तुलना में भी तेजी से काम किया जा सकता है (जो वास्तव में चारसेट दिखता है)। यह एक चूक / उपेक्षा है कि String(byte bytes[], int offset, int length, Charset charset)इसे कैसे लागू किया जाता है। वास्तव में, बड़े बाइट [] से एक छोटी सी स्ट्रिंग बनाते समय प्रदर्शन हिट बिल्कुल तुच्छ नहीं है।
बेस्ट जनस

7
कोई निष्पक्ष नहीं! आपके पास ऐसे महान संसाधनों तक पहुंच है। = (मैंने एक और जवाब देखा जहां आपने एक बार कहा था, "हाँ, इसलिए मैंने जोश [बलोच] से उसके बारे में पूछा ..."
केविनरपे

PrintStream चारसेट का समर्थन नहीं करता है
rofrol

102

दो साल बाद, और जावा 7 के स्टैंडर्डशर्ट्स अब 6 मानक चार्ट के लिए स्थिरांक को परिभाषित करता है।

यदि आप जावा 5/6 पर अटके हुए हैं, तो आप अमरूद के चार्टसेट स्थिरांक का उपयोग कर सकते हैं , जैसा कि केविन बॉरिलिन और जॉन स्कीट द्वारा सुझाया गया है।


29

मेरा तर्क है कि हम इससे बहुत बेहतर कर सकते हैं ... सीधे-सीधे उपलब्ध गारंटीकृत-से-उपलब्ध वर्णमाला क्यों नहीं हैं? Charset.UTF8एक संदर्भ होना चाहिए Charset, न कि एक स्ट्रिंग के रूप में नाम। इस तरह हमें UnsupportedEncodingExceptionसभी जगह नहीं संभालना होगा।

ध्यान रहे, मुझे यह भी लगता है कि .NET ने UTF-8 को हर जगह डिफ़ॉल्ट रूप से बेहतर रणनीति चुना। यह "ऑपरेटिंग सिस्टम डिफॉल्ट" एन्कोडिंग प्रॉपर्टी का नामकरण करके खराब कर दिया गया है Encoding.Default- जो कि केवल .NET के भीतर डिफ़ॉल्ट नहीं है :(

जावा के चारसेट समर्थन के बारे में शेख़ी पर वापस आना - क्यों FileWriter/ FileReaderजो एक लेता है के लिए एक निर्माता नहीं है Charset? मूल रूप से उन प्रतिबंधों के कारण लगभग बेकार वर्ग हैं - आपको लगभग हमेशा आउटपुट के लिए InputStreamReaderलगभग एक FileInputStreamया बराबर की आवश्यकता होती है :(

नर्स, नर्स - मेरी दवाई कहाँ है?

संपादित करें: यह मेरे लिए होता है कि यह वास्तव में सवाल का जवाब नहीं दिया है। वास्तविक उत्तर संभवतः या तो "इसमें शामिल किसी ने भी नहीं सोचा था" या "किसी ने सोचा था कि यह एक बुरा विचार था।" मैं दृढ़ता से सुझाव दूंगा कि इन-हाउस यूटिलिटी क्लासेस प्रदान करने वाले नाम या वर्ण कोडबेस के आसपास दोहराव से बचते हैं ... या आप केवल उसी का उपयोग कर सकते हैं जिसका उपयोग हमने Google में किया था जब यह उत्तर पहली बार लिखा गया था । (ध्यान दें कि जावा 7 के रूप में, आप StandardCharsetsइसके बजाय उपयोग करेंगे ।)


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

मैं एक विधि से काफी खुश होऊंगा, हालांकि मुझे उम्मीद है कि उन बहुत कम चार्ज को उत्सुकता से लोड करना एक महत्वपूर्ण लागत नहीं होगी।
जॉन स्कीट

1
हम उत्सुक क्लास लोडिंग को रोकने के लिए धर्मयुद्ध पर हैं। / बस "UTF-8" के लिए एक JDK की खोज की। 165 फ़ाइल (एस) में 270 मैच (एस) मिला। हालांकि इसमें से बहुत कुछ पुराने अपाचे कबाड़ में है (मेरा मानना ​​है कि मेरी टीम ने योगदान दिया है)।
टॉम हॉल्टिन -

1
@ टैकलाइन: मुझे लगता है कि उत्सुक क्लास लोडिंग उन चीजों में से एक है जो समय के साथ बढ़ते हैं। यहाँ कुछ कक्षाएं, वहाँ कुछ कक्षाएं - प्रत्येक व्यक्ति व्यक्तिगत रूप से पर्याप्त रूप से सहज लग रहा है - एक बड़ा अंतर ला सकता है।
जॉन स्कीट

अंतिम लिंक, अमरूद चार्ट्स के लिए, टूट गया है।
लार्स

28

जावा 1.7 में

import java.nio.charset.StandardCharsets

उदाहरण के लिए: StandardCharsets.UTF_8 StandardCharsets.US_ASCII


5

एन्कोडिंग एपीआई की वर्तमान स्थिति वांछित होने के लिए कुछ छोड़ देती है। जावा 6 एपीआई के कुछ हिस्सों को स्वीकार नहीं करते Charsetएक स्ट्रिंग के स्थान पर (में logging, dom.ls, PrintStream, वहाँ दूसरों हो सकता है)। यह मदद नहीं करता है कि मानक पुस्तकालय के विभिन्न हिस्सों के लिए एन्कोडिंग में अलग-अलग विहित नाम होने चाहिए।

मैं समझ सकता हूं कि चीजों को कैसे मिला है जहां वे हैं; मुझे यकीन नहीं है कि मेरे पास उन्हें कैसे ठीक करने के बारे में कोई शानदार विचार है।


स्वगत कथन के रूप में...

आप यहां Sun's Java 6 कार्यान्वयन के लिए नाम देख सकते हैं

यूटीएफ -8 के लिए, कैनोनिकल मूल्य के "UTF-8"लिए java.nioऔर इसके "UTF8"लिए java.langऔर हैं java.io। केवल एनकोडिंग में ऐनक का समर्थन करने के लिए JRE की आवश्यकता होती है: US-ASCII; ISO-8859-1; UTF-8; UTF-16BE; UTF-16LE; यूटीएफ -16


2
मैं PrintStream को स्वीकार नहीं करता, क्योंकि कक्षा स्पष्ट रूप से कहती है "PrintWriter वर्ग का उपयोग उन स्थितियों में किया जाना चाहिए जिनमें बाइट्स के बजाय वर्ण लिखने की आवश्यकता होती है।" (जो, सभी स्थितियों की तरह है ...)
केविन Bourrillion

2

मैंने बहुत पहले यूटीएफ_8, ISO_8859_1 और US_ASCII चारसेट स्थिरांक के साथ एक उपयोगिता वर्ग को परिभाषित किया है।

इसके अलावा, कुछ समय पहले (2 + वर्ष) मैं के बीच एक सरल प्रदर्शन परीक्षण किया new String( byte[], Charset )और new String( byte[], String charset_name )और की खोज की है कि बाद के कार्यान्वयन में काफी तेजी से। यदि आप स्रोत कोड पर हुड के नीचे एक नज़र डालते हैं तो आप देखेंगे कि वे वास्तव में काफी अलग पथ का अनुसरण करते हैं।

उसी कारण से मैंने उसी कक्षा में एक उपयोगिता शामिल की

public static String stringFromByteArray (
    final byte[] array,
    final Charset charset
)
{
    try
    {
        return new String( array, charset.name( ) )
    }
    catch ( UnsupportedEncodingException ex )
    {
        // cannot happen
    }
}

क्यों स्ट्रिंग (बाइट [], चारसेट) कंस्ट्रक्टर वही नहीं करता है, मुझे मारता है।


1
Charsetजरूरत, पंजीकृत किया जा नहीं तो अपवाद हो सकता है। IIRC, JDK7 में कुछ बदलाव किए गए ताकि यह ज्ञात-अच्छे Charsetकार्यान्वयन के लिए तेज़ी से हो सके (अतिरिक्त प्रतिलिपि को समाप्त करें)।
टॉम हॉल्टिन -
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.