मैंने इस मुद्दे पर अन्य पोस्ट पढ़ी हैं, लेकिन उनके द्वारा प्रस्तुत समाधान मेरे काम नहीं आया। वास्तव में, आधिकारिक जावा दस्तावेज़ीकरण भी अपेक्षित रूप से काम नहीं करता था (मैं जावा 11 का उपयोग कर रहा हूँ): https://docs.oracle.com/javase/tutorial/i18n/text/string.html

मेरी समस्या यह है कि मैं एक बाइट बफर से एक समय में एक बाइट पढ़ रहा हूं, उसे बाइट सरणी में डाल रहा हूं, और उस बाइट सरणी से स्ट्रिंग बना रहा हूं। मेरे द्वारा पढ़े गए बाइट एक एम्बेडेड सिस्टम से हैं जो केवल ISO-8859-1 बाइट्स भेज सकते हैं, इसलिए मैं ISO-8859-1 बाइट्स के साथ एक बाइट सरणी के साथ समाप्त होता हूं और जावा स्ट्रिंग जो मुझे मिल रही है वह इस प्रकार ISO-8859-1 है एन्कोडेड। यहां कोई समस्या नहीं है। IntelliJ में स्ट्रिंग इस तरह दिखती है:

enter image description here

मैं जिन बाइट्स को ISO-8859-1 से UTF-8 में बदलने की कोशिश कर रहा हूं, वे पीले रंग के हैं। मैं चाहता हूं कि वे यूटीएफ -8 हों, इसलिए अंत में "सी 9" बाइट को "सी 3 ए 9" बाइट्स द्वारा प्रतिस्थापित किया जाना चाहिए।

पहला चरण सही ढंग से काम करता है, मैं यह करता हूं: maintenanceResponseString.getBytes(StandardCharsets.UTF_8) और मुझे सही बाइट मिलते हैं जो मुझे चाहिए, स्ट्रिंग का UTF-8 एन्कोडिंग, यह अच्छा है:

enter image description here

समस्या यहां आती है, जब मैं इन नए (और GOOD) बाइट्स में से एक STRING बनाने का प्रयास करता हूं, जैसे:

new String(maintenanceResponseString.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8)

enter image description here

पुराने बाइट वापस आ गए हैं ?!! यह "getBytes (UTF-8)" जैसा है जो वास्तव में कभी नहीं हुआ। दस्तावेज़ीकरण कहता है कि ऐसा नहीं होना चाहिए... मैं यहाँ क्या खो रहा हूँ? मैंने परीक्षण किए हैं और स्ट्रिंग वास्तव में अभी भी आईएसओ-८८५९-१ एन्कोडेड है... मुझे नहीं पता कि यहां क्या हो रहा है। "गेटबाइट्स" से बाइट कहां हैं?

आप एक स्ट्रिंग को कैसे परिवर्तित करते हैं जिसमें ISO-8859-1 बाइट्स को UTF-8 बाइट्स में शामिल किया गया है? मैं विकल्पों से बाहर हूँ और मुझे इसे एक प्रो प्रोजेक्ट के लिए वास्तविक रूप से खराब करने की आवश्यकता है ... यह आसान होना चाहिए!

नोट: मैंने विकल्पों की कोशिश की है जैसे

ByteBuffer buffer = StandardCharsets.UTF_8.encode(s);
return StandardCharsets.UTF_8.decode(buffer).toString();

लेकिन ठीक ऐसा ही होता है।

मदद के लिए पहले ही धन्यवाद।

संपादित करें: टिप्पणियों में कुछ जानकारी के साथ कि जावा 9+ में स्ट्रिंग्स को आंतरिक रूप से यूटीएफ -16 के रूप में नहीं, बल्कि लैटिन -1 (क्यों ...) लैटिन -1" जब यह स्ट्रिंग का केवल डिफ़ॉल्ट प्रतिनिधित्व है यदि हम उस एन्कोडिंग को निर्दिष्ट नहीं करते हैं जिसे हम स्ट्रिंग प्रदर्शित करते समय उपयोग करना चाहते हैं

अब जो मुझे समझ में नहीं आता है, वह स्ट्रिंग स्वयं किसी भी एन्कोडिंग के लिए बाध्य नहीं है, और आप उस एन्कोडिंग को चुन सकते हैं जिसे आप इसे लिखे जाने पर प्रदर्शित करना चाहते हैं। असल में मेरा मुद्दा यह है कि स्ट्रिंग समाप्त होती है जिसे लैटिन -1 में जेएक्सबी मार्शलिंग के माध्यम से एक एक्सएमएल फ़ाइल में लिखा जाता है, और अब मुझे लगता है कि मुद्दे वहीं हैं ... जब मैं अपने काम के कंप्यूटर को फिर से एक्सेस करता हूं और यहां रिपोर्ट करता हूं तो मैं और खोदूंगा

-1
Genku 11 फरवरी 2021, 18:21
मैंने इसे पुन: पेश करने का प्रयास किया, लेकिन एक ऑनलाइन कंपाइलर यह भी नहीं दिखाता। क्या आप नमूने की तुलना में कुछ अलग कर सकते हैं?
 – 
Eugene
11 फरवरी 2021, 20:06
1
"एक स्ट्रिंग जिसमें ISO-8859-1 बाइट्स हैं" जैसी कोई चीज़ नहीं है। जावा सी नहीं है। स्ट्रिंग्स बाइट्स के अनुक्रम नहीं हैं, वे वर्णों के अनुक्रम हैं। स्ट्रिंग्स हमेशा UTF-16 होती हैं। जैसा कि आप जानते हैं, आप अलग-अलग वर्णसेट का उपयोग करके स्ट्रिंग्स को डीकोड कर सकते हैं, लेकिन एक बार जब आपके पास एक स्ट्रिंग ऑब्जेक्ट होता है, तो इसमें केवल एक एन्कोडिंग, अवधि होती है। (आंतरिक रूप से यह उन वर्णों को अलग-अलग तरीकों से प्रस्तुत कर सकता है, लेकिन कोड केवल उन वर्णों को UTF-16 char मान या int कोडपॉइंट मान के रूप में एक्सेस कर सकता है।)
 – 
VGR
11 फरवरी 2021, 22:16
ध्यान दें कि new String(maintenanceResponseString.getBytes(StandardCharsets.UTF_8), StandardCharsets.UTF_8) कुछ भी न करने के समान है। यह एक व्यर्थ दौर की यात्रा है।
 – 
VGR
11 फरवरी 2021, 22:18
जावा-9 के बाद से वे आंतरिक रूप से byte[] के रूप में संग्रहीत हैं और एन्कोडर या तो LATIN-1 या UTF-16 है, लेकिन हां, यह केवल आंतरिक रूप से है।
 – 
Eugene
11 फरवरी 2021, 23:12
"पहला चरण सही ढंग से काम करता है..." आपका पहला चरण StandardCharsets.ISO_8859_1 का बिल्कुल भी उपयोग नहीं करता है। मुझे यह बहुत कम लगता है कि UTF_8 का उपयोग करके किसी भी तरह उन आईएसओ 8859-1 बाइट्स को सही ढंग से डीकोड किया गया।
 – 
VGR
12 फरवरी 2021, 00:30

1 उत्तर

सबसे बढ़िया उत्तर

यह पता चला है कि स्ट्रिंग्स और "उनके एन्कोडिंग" में कुछ भी गलत नहीं था। क्या हुआ मैं वास्तव में भ्रमित हो गया क्योंकि डीबगर स्ट्रिंग की सामग्री को "डिफ़ॉल्ट आंतरिक स्टोरेज एन्कोडिंग" में दिखाता है, और वह आईएसओ -885 9 -1 है (लेकिन यूटीएफ -16 हो सकता है, स्ट्रिंग की सामग्री पर निर्भर करता है)।

JEP-254 से उद्धरण:

हम स्ट्रिंग वर्ग के आंतरिक प्रतिनिधित्व को UTF-16 चार सरणी से एक बाइट सरणी और एक एन्कोडिंग-फ्लैग फ़ील्ड में बदलने का प्रस्ताव करते हैं। नया स्ट्रिंग वर्ग स्ट्रिंग की सामग्री के आधार पर या तो ISO-8859-1/लैटिन-1 (एक बाइट प्रति वर्ण), या UTF-16 (प्रति वर्ण दो बाइट्स) के रूप में एन्कोड किए गए वर्णों को संग्रहीत करेगा। एन्कोडिंग ध्वज इंगित करेगा कि कौन सा एन्कोडिंग उपयोग किया जाता है।

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

मेरी समस्या वास्तव में तब थी जब मैं स्प्रिंग रेस्ट टेम्पलेट के साथ एक HTTP अनुरोध में स्ट्रिंग भेज रहा था। मेरे पास अनुरोध में उपयोग करने के लिए "वर्णसेट" निर्दिष्ट करने वाला शीर्षलेख नहीं था, और यदि अन्यथा नहीं बताया गया तो RestTemplate ISO-8859-1 पर डिफ़ॉल्ट है। मैंने वर्णसेट = utf-8 जोड़ा, और स्ट्रिंग को अनुरोध में UTF-8 के रूप में सही ढंग से लिखा गया था।

मदद के लिए @VGR @Eugene @skomisa को धन्यवाद

0
Genku 16 फरवरी 2021, 11:56