जावा और इसके विपरीत में पूर्णांक के लिए एक बाइट सरणी में कनवर्ट करें


139

मैं जावा में बाइट सरणियों में कुछ डेटा संग्रहीत करना चाहता हूं। मूल रूप से सिर्फ नंबर जो प्रति नंबर 2 बाइट्स तक ले सकते हैं।

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


4
कितना है आप थोड़ा स्थानान्तरण समझते हैं? ऐसा लगता है कि प्रश्न वास्तव में "क्या है बिट शिफ्टिंग करते हैं" बाइट सरणियों के रूपांतरण के बारे में अधिक, वास्तव में - यदि आप वास्तव में समझना चाहते हैं कि रूपांतरण कैसे काम करेगा।
जॉन स्कीट

1
(बस स्पष्ट करने के लिए, मैं या तो प्रश्न के साथ ठीक हूं, लेकिन यह स्पष्ट करने लायक है कि आप कौन सा प्रश्न वास्तव में उत्तर देना चाहते हैं। आपको एक उत्तर प्राप्त होने की संभावना है जो आपके लिए अधिक उपयोगी है।)
जॉन स्कीट

ठीक है मैं आपकी बात मान गया! टिप्पणी के लिए धन्यवाद। मुझे पता है कि मैं किस चीज की शिफ्टिंग करता हूं, मुझे अभी तक समझ नहीं आया कि बाइट सरणियों को परिवर्तित करने के लिए इसका क्या उपयोग किया जाता है।
क्रिस

3
@prekageo और Jeff Mercado आपके दो उत्तर के लिए धन्यवाद। prekageo ने एक अच्छी व्याख्या दी कि यह कैसे किया जाता है, अच्छा लिंक! यह मेरे लिए बहुत स्पष्ट है। और जेफ मर्कडोस समाधान ने मेरे पास मौजूद समस्या को हल किया।
क्रिस

जवाबों:


230

java.nioविशेष रूप से, नामस्थान में पाए जाने वाले वर्गों का उपयोग करें ByteBuffer। यह आपके लिए सभी काम कर सकता है।

byte[] arr = { 0x00, 0x01 };
ByteBuffer wrapped = ByteBuffer.wrap(arr); // big-endian by default
short num = wrapped.getShort(); // 1

ByteBuffer dbuf = ByteBuffer.allocate(2);
dbuf.putShort(num);
byte[] bytes = dbuf.array(); // { 0, 1 }

2
क्या यह बहुत महंगा है यदि बाइट सरणी में केवल 1 या 2 पूर्णांक हो? निर्माण की लागत के बारे में निश्चित नहीं है ByteBuffer
मेव कैट 2012

आप 2-4 बाइट विखंडू में बाइनरी डेटा के साथ कितनी बार काम कर रहे हैं? वास्तव में? एक समझदार कार्यान्वयन या तो BUFSIZ विखंडू (आमतौर पर 4kb) में इसके साथ काम करेगा या अन्य IO पुस्तकालयों का उपयोग करेगा जो इस विस्तार को छुपाता है। डेटा के बफ़र्स पर काम करने के लिए समर्पित ढांचे के भीतर एक पूरी लाइब्रेरी है। जब आप अच्छे कारण के बिना सामान्य संचालन लागू करते हैं तो आप अपने और अपने कोड के अन्य रखवाले के लिए एक सेवा करते हैं (यह पूर्ण या अन्य महत्वपूर्ण संचालन हो)। ये बफ़र्स केवल रैपर हैं जो सरणियों पर काम करते हैं, और कुछ नहीं।
जेफ

आप एक अमूर्त वर्ग को कैसे त्वरित कर सकते हैं?

1
@JaveneCPPMcGowan इस उत्तर में कोई प्रत्यक्ष तात्कालिकता मौजूद नहीं है। यदि आप कारखाने के तरीकों का मतलब wrapऔर allocate, वे अमूर्त वर्ग का एक उदाहरण नहीं लौटाते हैं ByteBuffer
मार्को टोपोलनिक

3 बाइट स्ट्राइड के लिए समाधान नहीं। हम प्राप्त कर सकते हैं Char, Short, Int। मुझे लगता है कि मैं 4 बाइट्स को पैड कर सकता हूं और हर बार 4 वें को छोड़ सकता हूं, लेकिन मैं नहीं करूंगा।
जॉन

128
byte[] toByteArray(int value) {
     return  ByteBuffer.allocate(4).putInt(value).array();
}

byte[] toByteArray(int value) {
    return new byte[] { 
        (byte)(value >> 24),
        (byte)(value >> 16),
        (byte)(value >> 8),
        (byte)value };
}

int fromByteArray(byte[] bytes) {
     return ByteBuffer.wrap(bytes).getInt();
}
// packing an array of 4 bytes to an int, big endian, minimal parentheses
// operator precedence: <<, &, | 
// when operators of equal precedence (here bitwise OR) appear in the same expression, they are evaluated from left to right
int fromByteArray(byte[] bytes) {
     return bytes[0] << 24 | (bytes[1] & 0xFF) << 16 | (bytes[2] & 0xFF) << 8 | (bytes[3] & 0xFF);
}

// packing an array of 4 bytes to an int, big endian, clean code
int fromByteArray(byte[] bytes) {
     return ((bytes[0] & 0xFF) << 24) | 
            ((bytes[1] & 0xFF) << 16) | 
            ((bytes[2] & 0xFF) << 8 ) | 
            ((bytes[3] & 0xFF) << 0 );
}

जब हस्ताक्षरित बाइट्स को एक इंट में पैक किया जाता है, तो प्रत्येक बाइट को बंद करने की आवश्यकता होती है क्योंकि अंकगणित पदोन्नति नियम (जेएलएस, रूपांतरण और प्रचार में वर्णित) के कारण यह 32 बिट्स (शून्य-विस्तारित की तुलना में) पर हस्ताक्षरित है।

जोशुआ बलोच और नील गेयर द्वारा जावा पूज़लर्स ("ए बिग डिलाइट इन ए बाइट") में वर्णित इस से संबंधित एक दिलचस्प पहेली है। जब एक बाइट मान की इंट मान से तुलना की जाती है, तो बाइट को एक इंट में बढ़ाया जाता है और फिर इस मूल्य की तुलना दूसरे इंट से की जाती है

byte[] bytes = (…)
if (bytes[0] == 0xFF) {
   // dead code, bytes[0] is in the range [-128,127] and thus never equal to 255
}

ध्यान दें कि जावा में 16-बिट अहस्ताक्षरित पूर्णांक प्रकार के अपवाद के साथ सभी संख्यात्मक प्रकारों पर हस्ताक्षर किए जाते हैं।


मुझे लगता है कि & 0xFFएस अनावश्यक हैं।
ओरिए पोपॉस्की

11
@Leifricson मुझे विश्वास है कि & 0xFFएस आवश्यक हैं क्योंकि यह जेवीएम को हस्ताक्षरित बाइट को केवल एक बिट में सेट के साथ पूर्णांक में परिवर्तित करने के लिए कहता है। अन्यथा बाइट -1 (0xFF) इंट -1 (0xFFFFFFFF) में बदल जाएगा। मैं गलत हो सकता है और यहां तक ​​कि अगर मैं हूं तो यह चोट नहीं करता है और चीजों को स्पष्ट करता है।
कोडरफॉर्फ़िन

4
और 0xFF वास्तव में अनिवार्य है। byte b = 0; b |= 0x88; System.out.println(Integer.toString(b, 16)); //Output: -78 System.out.println(Integer.toString(b & 0xFF, 16)); //Output: 88
HBN

1
@ptntialunrlsd वास्तव में नहीं। आप प्रदर्शन से पहले और पर आपरेशन byte0xFF (साथ int), JVM डाली जाएगा byteकरने intके साथ 1 बढ़ाया या 0 विस्तारित सा पहली प्रमुख अनुसार। जावा में कोई अहस्ताक्षरित बाइट नहीं है , byteहमेशा हस्ताक्षरित होते हैं।
नीर

2
जब बाइट सरणी से int पार्स, बाइट सरणी के आकार पर ध्यान दें, अगर यह 4 बाइट्स से अधिक है, तो डॉक्स के अनुसार ByteBuffer.getInt(): Reads the next four bytes at this buffer's current positionकेवल पहले 4 बाइट्स पार्स किए जाएंगे, जो कि आपको नहीं चाहिए।
बिन

56

तुम भी चर लंबाई बाइट्स के लिए BigInteger का उपयोग कर सकते हैं। आप इसे अपनी जरूरतों के हिसाब से लंबे, इंट या शॉर्ट में बदल सकते हैं।

new BigInteger(bytes).intValue();

या ध्रुवीयता को निरूपित करने के लिए:

new BigInteger(1, bytes).intValue();

बाइट्स वापस पाने के लिए:

new BigInteger(bytes).toByteArray()

1
ध्यान दें कि 1.8 से, यह intValueExactनहीं हैintValue
अभिजीत सरकार

5

एक बुनियादी कार्यान्वयन कुछ इस तरह होगा:

public class Test {
    public static void main(String[] args) {
        int[] input = new int[] { 0x1234, 0x5678, 0x9abc };
        byte[] output = new byte[input.length * 2];

        for (int i = 0, j = 0; i < input.length; i++, j+=2) {
            output[j] = (byte)(input[i] & 0xff);
            output[j+1] = (byte)((input[i] >> 8) & 0xff);
        }

        for (int i = 0; i < output.length; i++)
            System.out.format("%02x\n",output[i]);
    }
}

चीजों को समझने के लिए आप इस WP लेख को पढ़ सकते हैं: http://en.wikipedia.org/wiki/Endianness

उपरोक्त स्रोत कोड आउटपुट होगा 34 12 78 56 bc 9a। पहले 2 बाइट्स ( 34 12) पहले पूर्णांक का प्रतिनिधित्व करते हैं, आदि। उपरोक्त स्रोत कोड पूर्णांक प्रारूप में पूर्णांक एनकोड करता है।


2
/** length should be less than 4 (for int) **/
public long byteToInt(byte[] bytes, int length) {
        int val = 0;
        if(length>4) throw new RuntimeException("Too big to fit in int");
        for (int i = 0; i < length; i++) {
            val=val<<8;
            val=val|(bytes[i] & 0xFF);
        }
        return val;
    }

0

किसी ऐसी आवश्यकता के साथ जहां उन्हें बिट्स से पढ़ना पड़ता है, कह सकते हैं कि आपको केवल 3 बिट्स से पढ़ना होगा लेकिन आपको साइन इन किए गए पूर्णांक की आवश्यकता है:

data is of type: java.util.BitSet

new BigInteger(data.toByteArray).intValue() << 32 - 3 >> 32 - 3

मैजिक नंबर 3को बिट्स की संख्या के साथ बदला जा सकता है (बाइट्स नहीं) जो आप उपयोग कर रहे हैं।


0

जैसा कि अक्सर, अमरूद की आपको आवश्यकता होती है।

बाइट सरणी से इंट में जाने के लिए: यहाँInts.fromBytesArray डॉक्टर

Int से बाइट अरै तक जाने के लिए:, यहाँInts.toByteArray doc


-7

मुझे लगता है कि यह इंट कास्ट करने का सबसे अच्छा तरीका है

   public int ByteToint(Byte B){
        String comb;
        int out=0;
        comb=B+"";
        salida= Integer.parseInt(comb);
        out=out+128;
        return out;
    }

स्ट्रिंग के लिए पहली वापसी बाइट

comb=B+"";

अगला कदम एक int पर वापस आता है

out= Integer.parseInt(comb);

लेकिन बाइट्स इस रीज़न के लिए -128 से 127 तक रोष में है, मुझे लगता है कि बेहतर रेज़ 0 से 255 का उपयोग करना है और आपको केवल ऐसा करने की आवश्यकता है:

out=out+256;

ये गलत है। बाइट 0x01 पर विचार करें। आपका तरीका 129 आउटपुट होगा जो गलत है। 0x01 को पूर्णांक का उत्पादन करना चाहिए। यदि आप पूर्णांक से प्राप्त पूर्णांक ऋणात्मक है तो आपको केवल 128 जोड़ना चाहिए।
डिस्कलोजर

मेरा मतलब है कि आपको 256 जोड़ना चाहिए 128 नहीं। बाद में इसे संपादित नहीं कर सकता।
डिस्कलोजर

256 को जोड़ने के लिए पोस्ट बदली गई क्योंकि यह दूसरों के लिए उपयोगी हो सकता है!
apmartin1991

यह बहुत सी कास्टिंग करता है और नई ऑब्जेक्ट्स बनाता है (लगता है कि यह छोरों के लिए कर रहा है) जो प्रदर्शन को नीचा दिखा सकता है, संख्याओं को पार्स करने के तरीके के बारे में संकेत के लिए Integer.toString () विधि की जांच करें।
मार्कोस वास्कोनसेलोस

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