2014-09-19 4 views
8
byte[] byteArray = Charset.forName("UTF-8").encode("hello world").array(); 
System.out.println(byteArray.length); 

कोड की उपरोक्त पंक्ति 12 प्रिंट क्यों करती है, क्या इसकी बजाय 11 प्रिंटिंग नहीं होनी चाहिए?बाइटबफर

+0

है मुझे लगता है कि ध्यान से पहले बिना ByteBuffer.array विधि का उपयोग नहीं करने के लिए है इस से बाहर शुद्ध दस्तावेज पढ़ना। –

+0

मुझे आश्चर्य है कि आपके पास बैकिंग सरणी के लिए सार्वजनिक पहुंच है, बजाय पाने और विधियों का उपयोग करने के लिए मजबूर होना। – azurefrog

उत्तर

11

सरणी की लंबाई ByteBuffer के आकार है ' की क्षमता, जो उत्पन्न होती है, लेकिन आपके द्वारा एन्कोडिंग वाले वर्णों की संख्या के बराबर नहीं होती है। कैसे हम एक ByteBuffer के लिए स्मृति को आबंटित पर एक नज़र डालते हैं ...

आप encode() विधि और गहराई में जाने हैं, तो आप पाएंगे कि CharsetEncoder#encode(CharBuffer) इस तरह दिखता है:

public final ByteBuffer encode(CharBuffer in) 
    throws CharacterCodingException 
{ 
    int n = (int)(in.remaining() * averageBytesPerChar()); 
    ByteBuffer out = ByteBuffer.allocate(n); 
    ... 

मेरी डिबगर के अनुसार, averageBytesPerCharUTF_8$Encoder1.1 है, और इनपुट String में 11 वर्ण हैं। 11 * 1.1 = 12.1, और कोड एक int जब यह गणना करता है करने के लिए कुल डाले, तो ByteBuffer की जिसके परिणामस्वरूप आकार 12.

+5

वाह, मुझे आश्चर्य है कि उस औसत के साथ कौन आया, और उन्होंने किस डेटा सेट का उपयोग किया।किसी भी तरह, यह मुझे सांख्यिकीविद के बारे में मजाक की याद दिलाता है जो अपने सिर को ओवन और उसके पैरों को फ्रीजर में चिपकता है, और खुद को, औसत, आराम से गर्म होने की घोषणा करता है। –

1

क्योंकि यह ByteBuffer देता है। वह बफर की क्षमता (वास्तव में संभावित स्लाइसिंग के कारण भी नहीं), कितने बाइट्स का उपयोग नहीं किया जाता है। यह थोड़ा सा है कि कैसे malloc(10) स्मृति के 32 बाइट्स लौटने के लिए स्वतंत्र है।

System.out.println(Charset.forName("UTF-8").encode("hello world").limit()); 

यह 11 (अपेक्षित) है।

+0

मुझे ऐसा नहीं लगता है। यदि आपने एक खाली सरणी बनाई है, तो यह किसी चीज़ पर डिफॉल्ट हो जाती है और असाइनमेंट के बाद उपयोग किए गए बाइट्स की संख्या से अधिक हो सकती है, लेकिन इस मामले में, प्रतिलिपि कन्स्ट्रक्टर को बुलाया जाएगा और मैं उम्मीद करता हूं कि सरणी प्रारंभ हो जाएगी – ventsyv

+0

जब आप एक सरणी बनाते हैं, तो '। लम्बाई' लंबाई की लंबाई होगी (जो जावा स्पेक में है)। इस मामले में, 'एनकोड()' यह नहीं कहता कि यह क्या करेगा, बस यह कि आपने 'एन्कोडेड वर्णों' के साथ 'बाइटबफर' वापस कर दिया है, जिसके लिए आपने पूछा था। दूसरों ने इसमें खोला, और यह एक कार्यान्वयन विस्तार है, इसलिए यह व्यवहार JVM संस्करणों और कार्यान्वयन के बीच भी भिन्न होगा। –

+0

ठीक है, यह समझ में आता है। – ventsyv

0
import java.nio.charset.*; 
public class ByteArrayTest { 
    public static void main(String[] args) { 
     String theString = "hello world"; 
     System.out.println(theString.length()); 
     byte[] byteArray = Charset.forName("UTF-8").encode(theString).array(); 
     System.out.println(byteArray.length); 
     for (int i = 0; i < byteArray.length; i++) { 
      System.out.println("Byte " + i + " = " + byteArray[i]); 
     } 
    } 
} 

परिणाम:

C:\JavaTools>java ByteArrayTest 
11 
12 
Byte 0 = 104 
Byte 1 = 101 
Byte 2 = 108 
Byte 3 = 108 
Byte 4 = 111 
Byte 5 = 32 
Byte 6 = 119 
Byte 7 = 111 
Byte 8 = 114 
Byte 9 = 108 
Byte 10 = 100 
Byte 11 = 0 

सरणी, अशक्त-समाप्त है जैसे किसी भी अच्छे सी-स्ट्रिंग होगा।

(लेकिन जाहिरा तौर पर वास्तविक कारण परतदार विधि array। यह शायद, "उत्पादन" कोड में नहीं किया जाना चाहिए बड़ी सावधानी से छोड़कर। है)

+3

मुझे नहीं लगता कि पिछला 0 बाइट एक शून्य टर्मिनेटर है, जितना अप्रयुक्त बफर स्पेस – Andreas

+0

@ एंड्रियास - हाँ, आप शायद सही हैं - [array] (http://docs.oracle.com/javase/7 /docs/api/java/nio/ByteBuffer.html#array%28%29) एक अर्ध-बोगस ऑपरेशन है जो बाइटबफर के आंतरिक बफर को लौटाता है, और इसलिए कोई बात नहीं है कि यह कितना बड़ा होगा। –

+0

@ एंड्रियास: जावा रनटाइम (मुझे कल्पना है) सी में कार्यान्वित किया गया है, इसलिए स्ट्रिंग्स को गुप्त रूप से शून्य-समाप्त होने के लिए यह सुविधाजनक हो सकता है। :-) –

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