मैं जावा String
कैसे छोटा कर सकता हूं ताकि मुझे पता चले कि यह यूटीएफ -8 एन्कोडेड होने के बाद बाइट्स स्टोरेज की एक निश्चित संख्या में फिट होगा?यूटीएफ -8 एन्कोड किए जाने के बाद, किसी दिए गए बाइट्स में फ़िट होने के लिए मैं एक जावा स्ट्रिंग को कैसे छोटा कर सकता हूं?
उत्तर
यहाँ एक सरल पाश है कि मायने रखता है कितना बड़ा UTF-8 प्रतिनिधित्व होने जा रहा है है, और जब यह पार हो गई है ट्रंकेटस:
public static String truncateWhenUTF8(String s, int maxBytes) {
int b = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// ranges from http://en.wikipedia.org/wiki/UTF-8
int skip = 0;
int more;
if (c <= 0x007f) {
more = 1;
}
else if (c <= 0x07FF) {
more = 2;
} else if (c <= 0xd7ff) {
more = 3;
} else if (c <= 0xDFFF) {
// surrogate area, consume next char as well
more = 4;
skip = 1;
} else {
more = 3;
}
if (b + more > maxBytes) {
return s.substring(0, i);
}
b += more;
i += skip;
}
return s;
}
यह इनपुट स्ट्रिंग में दिखाई देने वाले surrogate pairs को संभालता है। जावा के यूटीएफ -8 एन्कोडर (सही ढंग से) सरोगेट जोड़े को दो 3-बाइट अनुक्रमों के बजाय एक 4-बाइट अनुक्रम के रूप में आउटपुट करता है, इसलिए truncateWhenUTF8()
यह सबसे लंबी कटाई वाली स्ट्रिंग को वापस कर देगा। यदि आप कार्यान्वयन में सरोगेट जोड़े को अनदेखा करते हैं तो छिद्रित तारों को उनकी आवश्यकता से कम किया जा सकता है।
मुझे लगता है कि कोड पर परीक्षण का एक बहुत नहीं किया है, लेकिन यहां कुछ प्रारंभिक परीक्षण:
private static void test(String s, int maxBytes, int expectedBytes) {
String result = truncateWhenUTF8(s, maxBytes);
byte[] utf8 = result.getBytes(Charset.forName("UTF-8"));
if (utf8.length > maxBytes) {
System.out.println("BAD: our truncation of " + s + " was too big");
}
if (utf8.length != expectedBytes) {
System.out.println("BAD: expected " + expectedBytes + " got " + utf8.length);
}
System.out.println(s + " truncated to " + result);
}
public static void main(String[] args) {
test("abcd", 0, 0);
test("abcd", 1, 1);
test("abcd", 2, 2);
test("abcd", 3, 3);
test("abcd", 4, 4);
test("abcd", 5, 4);
test("a\u0080b", 0, 0);
test("a\u0080b", 1, 1);
test("a\u0080b", 2, 1);
test("a\u0080b", 3, 3);
test("a\u0080b", 4, 4);
test("a\u0080b", 5, 4);
test("a\u0800b", 0, 0);
test("a\u0800b", 1, 1);
test("a\u0800b", 2, 1);
test("a\u0800b", 3, 1);
test("a\u0800b", 4, 4);
test("a\u0800b", 5, 5);
test("a\u0800b", 6, 5);
// surrogate pairs
test("\uD834\uDD1E", 0, 0);
test("\uD834\uDD1E", 1, 0);
test("\uD834\uDD1E", 2, 0);
test("\uD834\uDD1E", 3, 0);
test("\uD834\uDD1E", 4, 4);
test("\uD834\uDD1E", 5, 4);
}
अपडेट किया गया संशोधित कोड उदाहरण, यह अब सरोगेट जोड़े संभालती है।
यूटीएफ -8 एन्कोडिंग में एक साफ विशेषता है जो आपको यह देखने की अनुमति देती है कि आप बाइट-सेट में कहां हैं।
अपनी इच्छित सीमा सीमा पर स्ट्रीम की जांच करें।
- यदि इसकी उच्च बिट 0 है, तो यह एकल-बाइट चार है, बस इसे 0 के साथ बदलें और आप ठीक हैं।
- यदि इसकी उच्च बिट 1 है और अगली बिट है, तो आप एक बहु-बाइट चार की शुरुआत में हैं, तो बस उस बाइट को 0 पर सेट करें और आप अच्छे हैं।
- यदि उच्च बिट 1 है लेकिन अगली बिट 0 है, तो आप एक चरित्र के बीच में हैं, बफर के साथ वापस यात्रा करें जब तक कि आप एक बाइट हिट न करें जिसमें उच्च बिट्स में 2 या अधिक 1s हो और प्रतिस्थापित करें 0.
उदाहरण: यदि आपकी स्ट्रीम है: 31 33 31 सी 1 ए 3 32 33 00, तो आप अपनी स्ट्रिंग 1, 2, 3, 5, 6, या 7 बाइट्स लंबी बना सकते हैं, लेकिन 4 नहीं , क्योंकि यह सी 1 के बाद 0 डाल देगा, जो एक बहु-बाइट चार की शुरुआत है।
http://java.sun.com/j2se/1.5.0/docs/api/java/io/DataInput.html#modified-utf-8 संशोधित UTF-8 जावा और द्वारा प्रयुक्त एन्कोडिंग बताते हैं दर्शाता है कि यह जवाब सही क्यों है। – Alexander
बीटीडब्ल्यू, यह समाधान (एक बिल @ बिल जेम्स) @Matt Quail द्वारा वर्तमान में स्वीकृत उत्तर की तुलना में अधिक कुशल है, क्योंकि पूर्व में आपको सबसे अधिक 3 बाइट्स की जांच करने की आवश्यकता होती है, जबकि बाद में आपको सभी पात्रों का परीक्षण करने की आवश्यकता होती है ये पाठ। – Alexander
अलेक्जेंडर: पूर्व के लिए आपको पहले स्ट्रिंग को यूटीएफ 8 * में परिवर्तित करने की आवश्यकता होती है, जिसके लिए पाठ में सभी पात्रों पर पुनरावृत्ति की आवश्यकता होती है। –
आपको CharsetEncoder का उपयोग करना चाहिए, सरल getBytes()
+ कॉपी करें जितना आप आधे में यूटीएफ -8 चार्टर्स को काट सकते हैं।
कुछ इस तरह:
public static int truncateUtf8(String input, byte[] output) {
ByteBuffer outBuf = ByteBuffer.wrap(output);
CharBuffer inBuf = CharBuffer.wrap(input.toCharArray());
Charset utf8 = Charset.forName("UTF-8");
utf8.newEncoder().encode(inBuf, outBuf, true);
System.out.println("encoded " + inBuf.position() + " chars of " + input.length() + ", result: " + outBuf.position() + " bytes");
return outBuf.position();
}
यह मेरे लिए बहुत अच्छा काम करता है - शायद कम कुशल, लेकिन गलत होने के लिए बहुत कठिन है, और यह किसी भी चरित्र सेट के लिए काम करता है। एक त्वरित 'नई स्ट्रिंग (आउटपुट, 0, आउटपुट। लम्बाई - रिटर्न वैल्यू, चार्जसेट)' – ojrac
@ सिग्जेट का समाधान समान है और इसके अलावा वास्तविक लंबाई छिद्रित स्ट्रिंग देता है, केवल लंबाई –
आप बिना किसी रूपांतरण किए बाइट्स की संख्या की गणना कर सकते हैं।
foreach character in the Java string
if 0 <= character <= 0x7f
count += 1
else if 0x80 <= character <= 0x7ff
count += 2
else if 0x800 <= character <= 0xd7ff // excluding the surrogate area
count += 3
else if 0xdc00 <= character <= 0xffff
count += 3
else { // surrogate, a bit more complicated
count += 4
skip one extra character in the input stream
}
आप 4 बाइट प्रत्येक वैध किराए की जोड़ी के लिए किराए की जोड़े (D800-DBFF और U + DC00-U + DFFF) का पता लगाने और गिनती करने के लिए होगा। यदि आपको पहली श्रेणी में पहला मान मिलता है और दूसरी श्रेणी में दूसरा, यह ठीक है, उन्हें छोड़ दें और 4. जोड़ें लेकिन यदि नहीं, तो यह एक अवैध सरोगेट जोड़ी है। मुझे यकीन नहीं है कि जावा इसके साथ कैसे व्यवहार करता है, लेकिन आपके एल्गोरिदम को उस (असंभव) मामले में सही गिनती करना होगा।
यहां मैं जो आया हूं, वह मानक जावा एपीआई का उपयोग करता है, इसलिए सभी यूनिकोड अजीबता और सरोगेट जोड़े आदि के साथ सुरक्षित और संगत होना चाहिए।समाधान को http://www.jroller.com/holy/entry/truncating_utf_string_to_the से लिया गया है जिसमें नल के लिए जोड़े गए चेक और डिकोडिंग से बचने के लिए जब स्ट्रिंग maxBytes से कम बाइट्स है।
/**
* Truncates a string to the number of characters that fit in X bytes avoiding multi byte characters being cut in
* half at the cut off point. Also handles surrogate pairs where 2 characters in the string is actually one literal
* character.
*
* Based on: http://www.jroller.com/holy/entry/truncating_utf_string_to_the
*/
public static String truncateToFitUtf8ByteLength(String s, int maxBytes) {
if (s == null) {
return null;
}
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
byte[] sba = s.getBytes(charset);
if (sba.length <= maxBytes) {
return s;
}
// Ensure truncation by having byte buffer = maxBytes
ByteBuffer bb = ByteBuffer.wrap(sba, 0, maxBytes);
CharBuffer cb = CharBuffer.allocate(maxBytes);
// Ignore an incomplete character
decoder.onMalformedInput(CodingErrorAction.IGNORE)
decoder.decode(bb, cb, true);
decoder.flush(cb);
return new String(cb.array(), 0, cb.position());
}
'CharBuffer.allocate (maxBytes) 'बहुत आवंटित करता है। क्या यह 'CharBuffer.allocate (s.length()) 'हो सकता है? –
- 1. मैं एक स्ट्रिंग को यूटीएफ -8 में एन्कोड किए गए स्ट्रिंग में कैसे परिवर्तित कर सकता हूं और इसके विपरीत?
- 2. यूटीएफ -8 गुणों में जावा स्ट्रिंग को एन्कोड किया गया
- 3. PHP में एक यूटीएफ 8 स्ट्रिंग को कैसे छोटा करें?
- 4. एक्सस्ट्रीम फ्रेमवर्क का उपयोग करके मैं यूटीएफ -8 को कैसे एन्कोड कर सकता हूं?
- 5. मैं पायथन में एक यूटीएफ -8 एन्कोडेड स्ट्रिंग की बाइट लंबाई कैसे निर्धारित कर सकता हूं?
- 6. किसी दिए गए HTML तत्व के लिए मैं शैलियों को "रीसेट" कैसे कर सकता हूं?
- 7. मैं किसी दिए गए डिस्क के लिए SATA चैनल कैसे निर्धारित कर सकता हूं?
- 8. मैं पर्ल में एक इनपुट फ़ाइल को यूटीएफ -8 एन्कोडिंग में कैसे परिवर्तित कर सकता हूं?
- 9. स्ट्रिंग तुलना में यूटीएफ -8 बाइट ऑर्डर मार्कर को मैं कैसे अनदेखा कर सकता हूं?
- 10. मैं किसी दिए गए स्ट्रिंग के अवरोधक की ऊंचाई कैसे प्राप्त कर सकता हूं?
- 11. किसी utf-8 स्ट्रिंग में दिए गए वर्ण के लिए कोड पॉइंट नंबर कैसे प्राप्त करें?
- 12. यूनिकोड (यूटीएफ -8) कोडपॉइंट को बाइट्स
- 13. यूटीएफ -8 का उपयोग करके फ़ाइल को एन्कोड किए जाने पर मुझे कैसे पता चलेगा?
- 14. मैं यूटीएफ 8 में एन्कोड किए गए गैर-ASCII वर्णों को पर्ल में ASCII- समकक्ष में कैसे परिवर्तित कर सकता हूं?
- 15. मैं यूटीएफ -8 स्ट्रिंग को डार्ट में बाइट्स की सरणी में कैसे परिवर्तित करूं?
- 16. किसी दिए गए स्ट्रिंग
- 17. मैं एक MySQL कॉलम में संग्रहीत कच्चे बाइट्स को कैसे देख सकता हूं?
- 18. यूटीएफ 8 डीकोड या स्ट्रिंग पर एन्कोड को लागू करने के लिए कैसे पता लगाना है?
- 19. मैं पर्ल से यूटीएफ -8 कैसे आउटपुट कर सकता हूं?
- 20. यूटीएफ -8 एन्कोडेड चरित्र के लिए बाइट्स की अधिकतम संख्या क्या है?
- 21. मैं यूटीएफ 8 फ़ाइल
- 22. यूटीएफ -8 स्ट्रिंग
- 23. मैं MySQL वापसी यूटीएफ -8 कैसे बना सकता हूं?
- 24. एक बार उपयोग किए जाने के बाद मैं Django में सत्र कुंजी कैसे हटा सकता हूं?
- 25. एक यूटीएफ -8 एन्कोडेड स्ट्रिंग
- 26. जावा: एक स्ट्रिंग से यूटीएफ -8 हेक्स मान प्राप्त करें?
- 27. मैं यूटीएफ -8 स्ट्रिंग को जगह में कैसे उलटा सकता हूं?
- 28. जावा में एक यूटीएफ -8 स्ट्रिंग से 4 (+) - बाइट वर्णों को प्रतिस्थापित/निकालने के लिए कैसे?
- 29. यूटीएफ -8 को एक स्ट्रिंग को डीकोड करने के लिए कैसे सरल यूटीएफ -8 में दो बार एन्कोड किया गया है?
- 30. क्या मैं आयात किए जाने के बाद सास चर को ओवरराइड कर सकता हूं?
यूटीएफ -8 किसी भी यूसीएस 2 को एन्कोड कर सकता है 3 बाइट्स या उससे कम में चरित्र। उस पृष्ठ को देखें जो आप संदर्भित करते हैं। हालांकि, अगर आप यूसीएस 4 या यूटीएफ 16 (जो दोनों संपूर्ण वर्णसेट का संदर्भ दे सकते हैं) का पालन करना चाहते हैं, तो आपको यूटीएफ 8 में 6-बाइट वर्णों की अनुमति देनी होगी। – billjamesdev
विधेयक: विकिपीडिया पृष्ठ पर सीईएसयू -8 चर्चा देखें। मेरी समझ है कि यूटीएफ -8 को सरोगेट जोड़े को एक 4-बाइट अनुक्रम के रूप में एन्कोड करना है, दो 3-बाइट अनुक्रम नहीं। –
यह 2 तीन-बाइट नहीं है, यह यूसीएस 4 स्टोर करने के लिए 1 6-बाइट अनुक्रम तक है, जो एक पूर्ण 31-बिट चरित्र है, 2 16-बिट "जोड़े" (वह यूटीएफ 16) नहीं है। एक 6-बाइट seq = 1111110C 10CCCCCC 10CCCCCC 10CCCCCC 10CCCCCC 10CCCCCC जहां सी डेटा डेटा बिट्स हैं। अभी, 4 बाइट्स की आवश्यकता के लिए केवल पर्याप्त वर्ण उपयोग में हैं। – billjamesdev