दो बाइट सरणियों को समेटने का आसान तरीका


249

दो byteसरणियों को सुगम बनाने का आसान तरीका क्या है ?

कहो,

byte a[];
byte b[];

मैं दो byteसरणियों को कैसे एकत्र करूं और इसे दूसरे byteसरणी में संग्रहीत करूं?


3
कृपया ध्यान दें कि अपाचे कॉमन्स, गूगल के अमरूद, System.arrayCopy, ByteBufferऔर - तो कुशल लेकिन पढ़ने योग्य नहीं - ByteArrayOutputStreamसभी को कवर किया गया है। हमने यहां दिए गए उत्तरों के 7 से अधिक डुप्लिकेट प्राप्त किए हैं। कृपया कोई और अधिक पोस्ट न करें।
मार्टेन बॉड्यूज

जवाबों:


317

सबसे सीधा:

byte[] c = new byte[a.length + b.length];
System.arraycopy(a, 0, c, 0, a.length);
System.arraycopy(b, 0, c, a.length, b.length);

377

ऐसा करने का सबसे सुंदर तरीका है ByteArrayOutputStream

byte a[];
byte b[];

ByteArrayOutputStream outputStream = new ByteArrayOutputStream( );
outputStream.write( a );
outputStream.write( b );

byte c[] = outputStream.toByteArray( );

61
@vipw इसका कारण यह है कि यह सुरुचिपूर्ण है क्योंकि यदि / जब आप किसी तीसरे सरणी को बाद में संक्षिप्त करना चाहते हैं, तो आप बस लाइन जोड़ते हैं outputStream.write( c );- आपको वापस जाने की ज़रूरत नहीं है और उस पंक्ति को संपादित करें जहां आप परिणाम बाइट सरणी बनाते हैं। एरेस्कोपी विधि का उपयोग करने के विपरीत, सरणियों को फिर से आदेश देना सरल है।
वेन उरोदा

2
इसके अतिरिक्त यह केवल 2 बाइट सरणियों के साथ काम करते समय बहुत आसान है।
गार्डर

3
क्या यह सीपीयू बर्बाद कर रहा है और मेमोरी इस बात पर निर्भर करती है कि आप कितनी बार ऑपरेशन करते हैं। यदि यह एक अरब बार दूसरा है - निश्चित रूप से, इसे अनुकूलित करें। अन्यथा, पठनीयता और स्थिरता विजयी विचार हो सकते हैं।
15:30 बजे

5
यदि मेमोरी की खपत और / या प्रदर्शन एक चिंता का विषय है, a.length + b.lengthतो ByteArrayOutputStreamकंस्ट्रक्टर के लिए तर्क के रूप में उपयोग करना सुनिश्चित करें । ध्यान दें कि यह विधि अभी भी सभी बाइट्स को असाइन करने के लिए एक नए सरणी में कॉपी करेगी c[]! ByteBufferविधि के एक करीबी दावेदार पर विचार करें , जो स्मृति को बर्बाद नहीं करता है।
मार्टन बोदवेस

मैं वास्तव में इसे अंगूठा नहीं दे सकता क्योंकि यह सिर्फ एक कोड स्निपेट है। यहां अंतर्निहित टुकड़ों की कोई व्याख्या नहीं है, जो कि मुझे परवाह है (और मुझे लगता है कि ज्यादातर लोग होंगे)। अगर सिस्टम # arrayCopy (ऑब्जेक्ट, इंट, ऑब्जेक्ट, इंट, int) और ByteArrayOutputStream # put (बाइट []) के बीच प्रदर्शन तुलना होती है, तो मैं ख़ुशी से इसे दे दूंगा और दोनों विकल्पों के लिए विस्तृत परिदृश्य सबसे अच्छा है। इसके अलावा, कहा जा रहा है, जवाब भी arrayCopy शामिल करना चाहिए क्योंकि यह एक और समाधान है।
searchengine27

66

यहाँ का उपयोग कर एक अच्छा समाधान है अमरूद की com.google.common.primitives.Bytes:

byte[] c = Bytes.concat(a, b);

इस विधि के बारे में महान बात यह है कि इसमें एक वैरग हस्ताक्षर है:

public static byte[] concat(byte[]... arrays)

जिसका अर्थ है कि आप एक एकल विधि कॉल में मनमाने ढंग से सरणियों को संक्षिप्त कर सकते हैं।


30

एक और संभावना का उपयोग कर रहा है java.nio.ByteBuffer

कुछ इस तरह

ByteBuffer bb = ByteBuffer.allocate(a.length + b.length + c.length);
bb.put(a);
bb.put(b);
bb.put(c);
byte[] result = bb.array();

// or using method chaining:

byte[] result = ByteBuffer
        .allocate(a.length + b.length + c.length)
        .put(a).put(b).put(c)
        .array();

ध्यान दें कि सरणी को शुरू करने के लिए उचित आकार होना चाहिए, इसलिए आवंटन लाइन की आवश्यकता होती है (जैसा कि array()केवल ऑफसेट, स्थिति या सीमा को ध्यान में रखे बिना बैकिंग सरणी देता है)।


3
@click_whir क्षमा करें यार, लेकिन ReadTheDocs। ByteBuffer.allocate(int)एक स्थिर विधि है जो एक त्वरित java.nio.HeapByteBuffer, एक उपवर्ग लौटाती है ByteBuffer.put()और .compact()तरीकों - और किसी भी अन्य अमूर्त सत्ता - का ध्यान रखा जाता है।
kalefranz

@kalefranz निकाली गई compact()रेखा गलत है।
मार्टन बॉड्यूज

1
बाइटबफ़र की सरणी () विधि का उपयोग करने में ध्यान रखें - जब तक आप पूरी तरह से नहीं जानते कि आप क्या कर रहे हैं और रखरखाव एक मुद्दा नहीं है, तो कोई गारंटी नहीं है कि बाइटबफ़र में शून्य स्थिति हमेशा बाइट सरणी के सूचकांक 0 से मेल खाती है। देखें यहाँ । मैं जारी करके इस समस्या के समाधान bb.flip(); bb.get(result);की जगह में byte[] result = bb.array();लाइन।
दारकंडू

1
@DarqueSandu यद्यपि यह सामान्य रूप से अच्छी सलाह है , allocateविधि को सावधानीपूर्वक पढ़ने से निम्नलिखित का पता चलता है: "नई बफर की स्थिति शून्य होगी, इसकी सीमा इसकी क्षमता होगी, इसका निशान अपरिभाषित होगा, और इसके प्रत्येक तत्व को शून्य से प्रारंभ किया जाएगा। । इसमें एक बैकिंग एरे होगा, और इसकी एरे ऑफ़सेट शून्य होगी। " तो कोड के इस विशेष टुकड़े के लिए, जहां ByteBufferआंतरिक रूप से आवंटित किया गया है, यह कोई मुद्दा नहीं है।
Maarten Bodewes

13

एक अन्य तरीका एक उपयोगिता फ़ंक्शन का उपयोग करना है (यदि आप चाहें तो आप इसे सामान्य उपयोगिता वर्ग का एक स्थिर तरीका बना सकते हैं):

byte[] concat(byte[]...arrays)
{
    // Determine the length of the result array
    int totalLength = 0;
    for (int i = 0; i < arrays.length; i++)
    {
        totalLength += arrays[i].length;
    }

    // create the result array
    byte[] result = new byte[totalLength];

    // copy the source arrays into the result array
    int currentIndex = 0;
    for (int i = 0; i < arrays.length; i++)
    {
        System.arraycopy(arrays[i], 0, result, currentIndex, arrays[i].length);
        currentIndex += arrays[i].length;
    }

    return result;
}

इस तरह आमंत्रित करें:

byte[] a;
byte[] b;
byte[] result = concat(a, b);

यह 3, 4, 5 सरणियों आदि को समाप्‍त करने के लिए भी काम करेगा।

इसे इस तरह से करने से आपको तेज एरेस्कोपी कोड का लाभ मिलता है जो पढ़ने और बनाए रखने में भी बहुत आसान है।



11

यदि आप ByteBuffer@kalefranz को पसंद करते हैं, तो हमेशा byte[]एक पंक्ति में दो (या इससे भी अधिक) को एक साथ जोड़ने की सकारात्मकता होती है :

byte[] c = ByteBuffer.allocate(a.length+b.length).put(a).put(b).array();

इस एक के रूप में एक ही जवाब है, लेकिन 1 से अधिक साल देर से। विधि का उपयोग करता है, लेकिन बेहतर होगा कि मौजूदा जवाब में डाल दिया जाए।
मार्टन बॉड्यूज

11

आप Apache Commons Lang जैसे क्लीन कोड के लिए थर्ड पार्टी लाइब्रेरी का उपयोग कर सकते हैं और इसका उपयोग कर सकते हैं:

byte[] bytes = ArrayUtils.addAll(a, b);

1
मैंने कोशिश की ArrayUtils.addAll(a, b)और byte[] c = Bytes.concat(a, b), लेकिन बाद में तेज है।
कार्लोस एंड्रेस गार्सिया

शायद। मैं अमरूद पुस्तकालय नहीं जानता, अगर ऐसा है तो इसका उपयोग करना बेहतर है। क्या आपने बहुत बड़े सरणियों के लिए इसकी जाँच की?
टॉमाज़ प्रेज़बल्स्की

1
जब मैंने परीक्षण किया, तो द फर्ट्स एरे 68 एलिमेंट्स लेंथ था दूसरी 8790688 लंबाई।
कार्लोस आंद्रेस गार्सिया

5

दो या कई सरणियों के लिए, इस सरल और स्वच्छ उपयोगिता विधि का उपयोग किया जा सकता है:

/**
 * Append the given byte arrays to one big array
 *
 * @param arrays The arrays to append
 * @return The complete array containing the appended data
 */
public static final byte[] append(final byte[]... arrays) {
    final ByteArrayOutputStream out = new ByteArrayOutputStream();
    if (arrays != null) {
        for (final byte[] array : arrays) {
            if (array != null) {
                out.write(array, 0, array.length);
            }
        }
    }
    return out.toByteArray();
}

1
यह स्मृति को बर्बाद करता है। विधि दो छोटे सरणियों के लिए ठीक होगी, लेकिन यह निश्चित रूप से कचरा संग्रहकर्ता को अधिक सरणियों के लिए कर देगा।
मार्टन बॉडवेज

1

दो पीडीएफ बाइट सरणियों को मिलाएं

यदि आप दो बाइट सरणियों का विलय कर रहे हैं जिनमें पीडीएफ शामिल है, तो यह तर्क काम नहीं करेगा। हमें अपाचे से पीडीएफबॉक्स जैसे तीसरे पक्ष के उपकरण का उपयोग करने की आवश्यकता है:

ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
mergePdf.addSource(new ByteArrayInputStream(a));
mergePdf.addSource(new ByteArrayInputStream(b));
mergePdf.setDestinationStream(byteArrayOutputStream);
mergePdf.mergeDocuments();
c = byteArrayOutputStream.toByteArray();

इस सवाल का एक सा विषय है, लेकिन वास्तव में मैं क्या देख रहा था।
आमोस

1

यदि आप सरणियों के आकार के साथ गड़बड़ नहीं करना चाहते हैं, तो स्ट्रिंग स्ट्रिंग के जादू का उपयोग करें:

byte[] c = (new String(a, "l1") + new String(b, "l1")).getBytes("l1");

या अपने कोड में कहीं परिभाषित करें

// concatenation charset
static final java.nio.charset.Charset cch = java.nio.charset.StandardCharsets.ISO_8859_1;

और उपयोग करें

byte[] c = (new String(a, cch) + new String(b, cch)).getBytes(cch);

यह, निश्चित रूप से, +अतिरिक्त संचालक का उपयोग करके दो से अधिक स्ट्रिंग संघनन के साथ भी काम करता है ।


दोनों "l1"और ISO_8859_1पश्चिमी लैटिन 1 वर्ण सेट को इंगित करते हैं जो प्रत्येक चरित्र को एक बाइट के रूप में एन्कोड करता है। जैसा कि कोई मल्टी-बाइट अनुवाद नहीं किया जाता है, स्ट्रिंग में वर्णों को बाइट्स के समान मान होंगे (सिवाय इसके कि उन्हें हमेशा सकारात्मक मानों के रूप में व्याख्या किया जाएगा, जैसा charकि अहस्ताक्षरित है)। कम से कम ओरेकल के लिए रनटाइम प्रदान किया जाता है, इसलिए किसी भी बाइट को सही ढंग से "डिकोड किया गया" और फिर "एन्कोडेड" किया जाएगा।

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


@MaartenBodewes यदि आप "l1" (जो ISO 8859-1 के लिए सिर्फ एक उपनाम है) के बारे में निश्चित नहीं हैं, तो "निश्चित रूप से" शब्द का उपयोग न करें। किस विशेष बाइट मूल्य को मिटा दिया जाएगा? स्मृति के उपयोग के लिए, प्रश्न दो बाइट सरणियों को संक्षिप्त करने के आसान तरीके के बारे में था , न कि अधिकांश मेमोरी कुशल के बारे में।
जॉन मैक्लेने

1
मैंने कुछ चेतावनियाँ दी हैं और कुछ परीक्षण किए हैं। लैटिन 1 और ओरेकल के लिए रनटाइम (11) प्रदान करता है, यह काम करने लगता है। इसलिए मैंने अतिरिक्त जानकारी प्रदान की और अपनी टिप्पणी को हटा दिया। मुझे उम्मीद है कि यह आपके लिए ठीक है, अन्यथा कृपया वापस रोल करें।
मार्टन बॉड्यूज

0

इसे करने का मेरा तरीका है!

public static byte[] concatByteArrays(byte[]... inputs) {
    int i = inputs.length - 1, len = 0;
    for (; i >= 0; i--) {
        len += inputs[i].length;
    }
    byte[] r = new byte[len];
    for (i = inputs.length - 1; i >= 0; i--) {
        System.arraycopy(inputs[i], 0, r, len -= inputs[i].length, inputs[i].length);
    }
    return r;
}

विशेषताएं :

  • ...किसी भी संख्या के बाइट के साथ बुलाए जाने के लिए varargs ( ) का उपयोग करें []।
  • System.arraycopy()उच्च गति संचालन सुनिश्चित करने के लिए मशीन विशिष्ट देशी कोड के साथ लागू किया जाता है कि प्रयोग करें ।
  • सटीक आकार के साथ एक नया बाइट [] बनाएं जिसकी आवश्यकता है।
  • और चर का intपुन: उपयोग करके थोड़ा कम चर आवंटित करें ।ilen
  • स्थिरांक के साथ तेजी से तुलना।

ध्यान रखें :

ऐसा करने का बेहतर तरीका है, @Jonathan कोड को कॉपी करना । समस्या मूल वैरिएबल सरणियों से आती है, क्योंकि यह डेटा प्रकार किसी अन्य फ़ंक्शन के पास होने पर जावा नए चर बनाता है।


1
नहीं, ऐसा करने का वेन तरीका है , आपको 5 साल देर हो चुकी है।
मार्टेन बोडेवेस

@MaartenBodewes धन्यवाद, मैं आज कोडिंग व्यायाम करने के लिए आपकी टिप्पणी का उपयोग करता हूं, अब अधिक भिन्न है और बेहतर प्रदर्शन के साथ।
डेनियल डे लियोन

1
मुझे यकीन नहीं है कि यह बहुत ज्यादा मायने रखेगा, यह देखते हुए कि सरणी के आकार रनटाइम में भी नहीं बदलते हैं, लेकिन यह अब कम से कम दूसरे समाधान से अलग है।
मार्टन बॉड्यूज
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.