2011-04-11 17 views
20

मैं कुछ कार्यान्वयन-निर्भर चाल का उपयोग किये बिना रूपांतरण करना चाहता हूं। कोई सुझाव?मैं एक 4-बाइट सरणी को एक पूर्णांक में कैसे परिवर्तित कर सकता हूं?

+2

आप क्या बदलना चाहते हैं? आपका प्रश्न विशिष्ट नहीं है। आपके सरणी के चार बाइट्स क्या हैं? – bmargulies

उत्तर

57

आप अपने बाइट्स की endianness जानना चाहते हैं।

मानते हैं (जैसे @ व्हाइटफैंग 34) bytesbyte[] लंबाई 4 है, तो ...

बिग-endian:

int x = java.nio.ByteBuffer.wrap(bytes).getInt(); 

लिटिल-endian:

int x = java.nio.ByteBuffer.wrap(bytes).order(java.nio.ByteOrder.LITTLE_ENDIAN).getInt(); 
+1

+1 यह काम करता है और छोटे-अंत समर्थन के लिए एक अच्छा विकल्प प्रदान करता है। मैं सोच रहा था कि जावा ने ऐसा करने के लिए समर्थन किया था या नहीं। हालांकि यह इस मार्ग पर जाने के लिए एक वस्तु बनाता है। तो यह उतना कुशल नहीं है, हालांकि मुझे संदेह है कि यह ज्यादातर उपयोगों के लिए महत्वपूर्ण है। – WhiteFang34

23

bytes मान लिया जाये कि बड़े endian क्रम में एक पूर्णांक, आम तौर पर नेटवर्किंग में इस्तेमाल की एक byte[4] है:

int value = ((bytes[0] & 0xFF) << 24) | ((bytes[1] & 0xFF) << 16) 
     | ((bytes[2] & 0xFF) << 8) | (bytes[3] & 0xFF); 

& 0xFF जरूरी हैं क्योंकि byte जावा प्रवेश किया गया है और तुम यहाँ पर हस्ताक्षर किए बिट बनाए रखने की जरूरत है। आप इस के साथ प्रक्रिया को उल्टा कर सकते हैं:

bytes[0] = (byte) ((value >> 24) & 0xFF); 
bytes[1] = (byte) ((value >> 16) & 0xFF); 
bytes[2] = (byte) ((value >> 8) & 0xFF); 
bytes[3] = (byte) (value & 0xFF); 
+0

मैं गलत पढ़ रहा हूं लेकिन मुझे लगता है कि यह आपके द्वारा लिखे गए तरीके से बड़े-बड़े हैं। –

+0

@ डेविड: यह है। धन्यवाद, मैंने वास्तव में पहली बार गलत लेबल किया था। – WhiteFang34

+2

'बाइट []' से 'int' में कनवर्ट करते समय पहली '& 0xff' की आवश्यकता क्यों है? '<< 24' द्वारा हस्ताक्षरित हस्ताक्षरित मानों के लिए 1s अग्रणी नहीं हैं? जैसा कि मैं इसे समझता हूं '((बाइट्स [0] और 0xFF) << 24) 'इस मामले में' ((बाइट्स [0] << 24)' जैसा ही है। यदि 'बाइट [0]' हस्ताक्षरित है तो यह है हस्ताक्षरित int में परिवर्तित हो गया लेकिन '<< 24' मूल बाइट की 8 बिट्स को छोड़कर सबकुछ छोड़ देता है। साथ ही मुझे लगता है कि' और 0xff' का उपयोग मूल्यों के साथ मूल्य 1 के साथ प्रमुख बिट्स को छोड़ने के लिए किया जाता है ताकि उन्हें 0 बिट्स पर ऑर्डर न किया जा सके पिछले ऑपरेशन से। यह नहीं कह रहा है कि हस्ताक्षर किए गए बिट को गलत रखने के लिए '0xff' आवश्यक है? – petrn

6

आप सरणी के बाइट क्रम निर्दिष्ट करने की आवश्यकता है, लेकिन यह सोचते हैं कि bytes[0] तो सबसे महत्वपूर्ण बाइट है:

int res = ((bytes[0] & 0xff) << 24) | ((bytes[1] & 0xff) << 16) | 
      ((bytes[2] & 0xff) << 8) | (bytes[3] & 0xff); 

इस कोड को 100% पोर्टेबल, यह मानते हुए कि आप पहले स्थान पर बाइट सरणी बनाने के लिए रिवर्स एल्गोरिदम का उपयोग करते हैं।


बाइट आदेश समस्याओं भाषाओं जहां एक देशी पूर्णांक प्रकार और बाइट सरणी प्रकार के बीच डाल सकता में उत्पन्न होती हैं ... और फिर पता चलता है कि विभिन्न आर्किटेक्चर विभिन्न क्रम में एक पूर्णांक के बाइट्स की दुकान।

आप जावा में उस कलाकार को नहीं कर सकते हैं। तो जावा से जावा संचार के लिए, यह कोई मुद्दा नहीं होना चाहिए।

हालांकि, अगर आप सी या सी ++ में लागू किए गए कुछ रिमोट एप्लिकेशन को पैकेट भेज रहे हैं या प्राप्त कर रहे हैं, तो आपको नेटवर्क पैकेट में बाइट ऑर्डर का उपयोग करने के लिए "पता" होना चाहिए। इस पता लगाना/जानने के लिए कुछ वैकल्पिक रणनीतियों हैं:

  • हर कोई ऊपर के उदाहरण कोड के अनुसार तार पर सामान के लिए "नेटवर्क आदेश" (बड़े endian) का उपयोग करता है। छोटी-छोटी मशीनों पर गैर-जावा अनुप्रयोगों को बाइट्स को फ़्लिप करने की आवश्यकता होती है।

  • प्रेषक पता लगाता है कि रिसीवर किस आदेश को अपेक्षा करता है और डेटा को इकट्ठा करते समय उस आदेश का उपयोग करता है।

  • रिसीवर पता लगाता है कि प्रेषक किस आदेश का उपयोग करता है (उदाहरण के लिए पैकेट में ध्वज के माध्यम से) और तदनुसार डीकोड।

पहले दृष्टिकोण, सरल और सबसे व्यापक रूप से इस्तेमाल है, हालांकि यह 2 अनावश्यक endian सत्ता रूपांतरण की संभावना है, तो प्रेषक और प्राप्तकर्ता से थोड़ा-endian हैं।

http://en.wikipedia.org/wiki/Endianness

+0

क्या मानक लाइब्रेरी के माध्यम से ऐसा करने का कोई तरीका है? मुझे यह समझने में बहुत अच्छा नहीं लगता कि चीजें बाइट ऑर्डर हैं मशीनें मैं पैकेट भेज रहा हूं ... – Alex

+1

@Alex: मशीन के बाइट ऑर्डर इस गणना में कोई फर्क नहीं पड़ता है, यह आपके सरणी का बाइट ऑर्डर महत्वपूर्ण है। आपको यह निर्दिष्ट करना होगा कि भले ही आप मानक पुस्तकालय का उपयोग करें (यदि ऐसा करने के लिए एक मानक विधि है ... मुझे एक याद नहीं है) –

+0

आपको प्रत्येक बाइट्स को '0xFF' करने की आवश्यकता है क्योंकि जावा में' बाइट' हस्ताक्षरित है। हस्ताक्षरित बिट किसी भी संख्या के रास्ते में आता है जो बाइट्स के पहले बिट का उपयोग करता है। जैसे 384 से एक बाइट सरणी के एक पूर्णांक से पीछे की ओर जाने का प्रयास करें, जब आप पूर्णांक प्राप्त करने के लिए अपना कोड चलाते हैं तो आपको 384 के बजाय -128 मिल जाएगा। – WhiteFang34

4

अगर यह सही जावा वाक्य रचना है सुनिश्चित नहीं हैं कि देखें, लेकिन कैसे के बारे में:

int value = 0; 
for (i = 0; i <= 3; i++) 
    value = (value << 8) + (bytes[i] & 0xFF); 
+2

आपको अपने 'बाइट्स' ix ''xx' होना चाहिए क्योंकि' बाइट '(जावा में) नागामी हो सकता है और जावा आपके बाइट को नकारात्मक में परिवर्तित कर देगा 0-255 –

+0

@Yanick के बीच एक मान के बजाय पूर्णांक: धन्यवाद। मैंने अपनी पोस्ट को आपके सुधार के साथ संपादित किया है –

+0

यह काम नहीं करता है, यह हमेशा 0 देता है। आपको ऑपरेटर प्राथमिकता से बचने के लिए ब्रांड्स की आवश्यकता होती है: 'value = (value << 8) + (बाइट्स [i] और 0xFF); – WhiteFang34

-1
public static int toInt(byte[] bytes) { 
int result = 0; 
for (int i=0; i<3; i++) { 
    result = (result << 8) - Byte.MIN_VALUE + (int) bytes[i]; 
} 
return result; 
} 
+0

यह काम नहीं करता है।सभी शून्यों का एक बाइट सरणी 8421504 लौटाता है। – WhiteFang34

+0

अच्छी पकड़ है! –

1

मानते हुए अपने बाइट [] कहीं उदा से आते हैं एक धारा का उपयोग कर सकते

DataInputStream dis = ... // can wrap a new ByteArrayInputStream(bytes) 
int num = dis.readInt(); // assume big-endian. 

या

ByteChannel bc = ... // can be a SocketChannel 
ByteBuffer bb = ByteBuffer.allocate(64*1024); 

bc.read(bb); 
bb.flip(); 
if (bb.remaining()<4) // not enough data 

int num = bb.getInt(); 

जब आप डेटा भेजने के लिए, यदि आप बड़े endian या थोड़ा endian भेज रहे हैं पता होना चाहिए। आपको अन्य चीजों को मानना ​​है जैसे कि आप 4-बाइट हस्ताक्षरित पूर्णांक भेज रहे हैं या नहीं। एक बाइनरी प्रोटोकॉल धारणाओं से भरा है। (जो इसे अधिक कॉम्पैक्ट और तेज बनाता है, लेकिन पाठ से अधिक भंगुर)

यदि आप कई धारणाएं नहीं बनाना चाहते हैं, तो टेक्स्ट भेजें।

+1

'int num = dis.readInt(); // बड़े-एंडियन मानें। 'बहुत उपयोगी जानकारी है .. –

1

हम भी बनाने के लिए निम्नलिखित का उपयोग कर सकते इसे और अधिक गतिशील बाइट सरणी आकार
BigEndian स्वरूप:

public static int pareAsBigEndianByteArray(byte[] bytes) { 
    int factor = bytes.length - 1; 
    int result = 0; 
    for (int i = 0; i < bytes.length; i++) { 
     if (i == 0) { 
      result |= bytes[i] << (8 * factor--); 
     } else { 
      result |= bytes[i] << (8 * factor--); 
     } 
    } 
    return result; 
} 

लिटल एन्डियन स्वरूप:

public static int pareAsLittleEndianByteArray(byte[] bytes) { 
    int result = 0; 
    for (int i = 0; i < bytes.length; i++) { 
     if (i == 0) { 
      result |= bytes[i] << (8 * i); 
     } else { 
      result |= bytes[i] << (8 * i); 
     } 
    } 
    return result; 
} 

हो जाएगा ताकि बाइट्स परिवर्तित करने के लिए int के लिए आप बहुत मदद करता है मूल्य

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

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