2013-10-19 7 views
6

शीर्षक यह सब कहता है। बीच में स्ट्रिंग का उपयोग किए बिना स्ट्रिंगबिल्डर से बाइट [] में कनवर्ट करने का कोई तरीका है?जावा: स्ट्रिंगबफर टू बाइट [] बिना स्ट्रिंग

समस्या यह है कि मैं वास्तव में बड़े तारों (लाखों वर्णों) का प्रबंधन कर रहा हूं, और फिर मेरे पास एक चक्र है जो अंत में एक char जोड़ता है और बाइट प्राप्त करता है []। स्ट्रिंगबफर टू स्ट्रिंग को कनवर्ट करने की प्रक्रिया इस चक्र को बहुत धीमी गति से बनाती है।

क्या इसे पूरा करने का कोई तरीका है? अग्रिम में धन्यवाद!

+0

निकटतम आप प्राप्त कर सकते हैं 'char [] 'सरणी प्राप्त करना। स्ट्रिंगबफर # getChars (int, int, char [], int) –

+2

इसके बजाय [CharBuffer] (http://docs.oracle.com/javase/7/docs/api/java/nio/CharBuffer.html) का उपयोग क्यों नहीं करें? और फिर "charBuffer.array()" करते हैं? – tolitius

+2

क्या आप स्पष्टीकरण दे सकते हैं कि आपको इन सभी बड़े तारों को स्मृति में क्यों स्टोर करना होगा? क्या यह कोई उपयोगकर्ता इंतजार कर रहा है? क्या यह बदले में मैपरेडस या स्पार्क नौकरी बन सकता है? मुझे आश्चर्य है कि शायद यह सवाल एक वास्तुशिल्प डिजाइन गंध का एक लक्षण है। – Vidya

उत्तर

1

स्टार्टर्स के लिए, आपको शायद StringBuilder का उपयोग करना चाहिए, क्योंकि StringBuffer में सिंक्रनाइज़ेशन ओवरहेड होता है जो आमतौर पर अनावश्यक होता है।

दुर्भाग्य से, वहाँ byte रों पर सीधे जाने के कोई रास्ता नहीं है, लेकिन आप एक सरणी में char रों कॉपी या 0 से length() को पुनरावृति और प्रत्येक charAt() पढ़ सकते हैं।

+0

+1 और स्ट्रिंगबफर के लिए जावाडोक का कहना है कि आपको स्ट्रिंगबिल्डर का लगभग दस वर्षों तक उपयोग करना चाहिए। –

0

आप "लाखों वर्णों" के साथ पूरा करने की क्या कोशिश कर रहे हैं? क्या ये लॉग इन पार्स किए जाने की आवश्यकता है? क्या आप इसे केवल बाइट्स के रूप में पढ़ सकते हैं और ByteBuffer पर चिपके रह सकते हैं? तो फिर तुम कर सकते हैं:

buffer.array() 

एक byte[]

यह तुम क्या कर रहे है पर निर्भर करता है पाने के लिए, आप भी सिर्फ एक char[] या एक CharBuffer उपयोग कर सकते हैं: फिर

CharBuffer cb = CharBuffer.allocate(4242); 
cb.put("Depends on what it is you need to do"); 
... 

आप कर सकते हैं char[] प्राप्त करें:

cp.array() 

यह आरपीएल चीजों के लिए हमेशा अच्छा होता है, यह मजेदार है और बिंदु साबित करता है। जावा आरईपीएल कुछ हम के आदी रहे हैं नहीं है, लेकिन हे, Clojure दिन जो जावा धाराप्रवाह बोलती है को बचाने के लिए है:

user=> (import java.nio.CharBuffer) 
java.nio.CharBuffer 

user=> (def cb (CharBuffer/allocate 4242)) 
#'user/cb 

user=> (-> (.put cb "There Be") (.array)) 
#<char[] [[email protected]> 

user=> (-> (.put cb " Dragons") (.array) (String.)) 
"There Be Dragons" 
11

के रूप में कई पहले से ही सुझाव दिया है, आप CharBuffer वर्ग का उपयोग कर सकते, लेकिन एक नए CharBuffer आवंटन केवल आपकी समस्या को और खराब कर देगा।

इसके बजाय, आप सीधे अपने StringBuilder एक CharBuffer में, लपेट कर सकते हैं के बाद से StringBuilder CharSequence लागू करता है:

Charset charset = StandardCharsets.UTF_8; 
CharsetEncoder encoder = charset.newEncoder(); 

// No allocation performed, just wraps the StringBuilder. 
CharBuffer buffer = CharBuffer.wrap(stringBuilder); 

ByteBuffer bytes = encoder.encode(buffer); 

संपादित करें: ड्यूआर्टे सही ढंग से बताते हैं कि CharsetEncoder.encode विधि एक बफर जिसका समर्थन सरणी से बड़ा है वापस आ सकते हैं वास्तविक डेटा-अर्थ, इसकी क्षमता इसकी सीमा से बड़ी है। बाइटबफर से खुद को पढ़ने के लिए या बाइटबफर से बाहर बाइट सरणी पढ़ने के लिए जरूरी है जिसे सही आकार की गारंटी दी जाती है।

ByteBuffer byteBuffer = encoder.encode(buffer); 

byte[] array; 
int arrayLen = byteBuffer.limit(); 
if (arrayLen == byteBuffer.capacity()) { 
    array = byteBuffer.array(); 
} else { 
    // This will place two copies of the byte sequence in memory, 
    // until byteBuffer gets garbage-collected (which should happen 
    // pretty quickly once the reference to it is null'd). 

    array = new byte[arrayLen]; 
    byteBuffer.get(array); 
} 

byteBuffer = null; 
+0

+1 सही उत्तर के लिए जो सही ढंग से वर्णमाला एन्कोडिंग लागू करता है। –

+1

सावधान: ByteBuffer.array() पूरी बैकिंग सरणी देता है, जिसमें अतिरिक्त बाइट्स होंगे! –

0

आप प्रदर्शन चाहते हैं, मैं StringBuilder का उपयोग करें या एक बाइट [] नहीं बनाता: उत्तरार्द्ध मामले में, वहाँ कोई स्मृति में बाइट्स की दो प्रतियां होने से परहेज, संक्षेप में यद्यपि है। इसके बजाय आप स्ट्रीम में प्रगतिशील रूप से लिख सकते हैं जो डेटा को पहले स्थान पर ले जाएगा। यदि आप ऐसा नहीं कर सकते हैं, तो आप स्ट्रिंगबिल्डर से डेटा को राइटर में कॉपी कर सकते हैं, लेकिन स्ट्रिंगबिल्डर को पहले स्थान पर नहीं बनाना बहुत तेज़ है।

+0

हम धारा में प्रगतिशील रूप से लिखने के बारे में कैसे जाएंगे? मेरे पास बाइट [] – CyberMew

+0

में एक फ़ंक्शन ले रहा है, आपको उस कार्य के रूप में आवश्यकता है जिसे आप बाइट के साथ कॉल कर सकते हैं [] जिसे आपने अभी तक पढ़ा है उदा। https://docs.oracle.com/javase/7/docs/api/java/io/OutputStream.html#write(byte[ ],%20int,%20int) यह फ़ंक्शन आपको एक ही बाइट [] प्रत्येक का उपयोग करने की अनुमति देता है समय संसाधित डेटा के आकार के बावजूद मेमोरी खपत और कचरा निरंतर बनाते हैं। –

1

दुर्भाग्यवश, बाइटबफर की सरणी() विधि के साथ उस सौदे के ऊपर दिए गए उत्तर थोड़ा छोटी हैं ... समस्या यह है कि आवंटित बाइट [] आपकी अपेक्षा से अधिक होने की संभावना है। इस प्रकार, वहां नल बाइट्स का पीछा किया जाएगा जो छुटकारा पाने में मुश्किल हैं, क्योंकि आप जावा में "पुनः आकार" सरणी नहीं कर सकते हैं।

यहाँ एक लेख है कि और अधिक विस्तार में यह बताता है: http://worldmodscode.wordpress.com/2012/12/14/the-java-bytebuffer-a-crash-course/

2

आप कुछ और के साथ StringBuilder को बदलने के लिए तैयार हैं, अभी तक एक और संभावना एक Writer एक ByteArrayOutputStream द्वारा समर्थित होगा:

ByteArrayOutputStream bout = new ByteArrayOutputStream(); 
Writer writer = new OutputStreamWriter(bout); 
try { 
    writer.write("String A"); 
    writer.write("String B"); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
System.out.println(bout.toByteArray()); 

try { 
    writer.write("String C"); 
} catch (IOException e) { 
    e.printStackTrace(); 
} 
System.out.println(bout.toByteArray()); 

हमेशा के रूप में, आपका लाभ भिन्न हो सकता है।

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