इंटर्न को बिना बाइट और बैक में कैसे कन्वर्ट करें


92

मुझे एक नंबर को एक अहस्ताक्षरित बाइट में बदलने की आवश्यकता है। संख्या हमेशा 255 से कम या बराबर होती है, और इसलिए यह एक बाइट में फिट होगा।

मुझे उस बाइट को वापस उस नंबर में बदलना है। मैं जावा में कैसे करूंगा? मैंने कई तरीके आज़माए हैं और कोई भी काम नहीं कर रहा है। यहाँ मैं अब क्या करने की कोशिश कर रहा हूँ:

int size = 5;
// Convert size int to binary
String sizeStr = Integer.toString(size);
byte binaryByte = Byte.valueOf(sizeStr);

और अब उस बाइट को वापस संख्या में बदलने के लिए:

Byte test = new Byte(binaryByte);
int msgSize = test.intValue();

स्पष्ट रूप से, यह काम नहीं करता है। किसी कारण से, यह हमेशा संख्या को रूपांतरित करता है 65। कोई सुझाव?


मैंने यह तरीका भी आज़माया: crazysquirrel.com/computing/java/basics/… - काम नहीं करता।
12:52 बजे डार्कस्की

जवाबों:


200

जावा में हमेशा एक बाइट पर हस्ताक्षर किए जाते हैं। बाइनरी-एंडिंग के द्वारा आपको इसका अहस्ताक्षरित मान 0xFF के साथ मिल सकता है, हालाँकि:

int i = 234;
byte b = (byte) i;
System.out.println(b); // -22
int i2 = b & 0xFF;
System.out.println(i2); // 234

मुझे अभी भी 65 मिल रहे हैं ... ऐसा क्यों है?
अंधेरा

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

1
getInt का उपयोग अपने int को वापस पाने के लिए, और int को बाइट के रूप में बदलने के लिए। एक इंट एक इंट है। यह कहाँ से आता है कोई फर्क नहीं पड़ता।
बजे जेबी निज़ेट

18
0xFFबिना किसी पूर्णांक के बिटवाइज़ और परिणाम क्यों होता है ? कुछ स्पष्टीकरण वास्तव में सहायक होंगे।
user462455

2
जावा 8 एक ही विधि का उपयोग करें: सार्वजनिक स्थैतिक int tonsignedInt (बाइट x) {वापसी ((इंट) x) & 0 %ff; }
डैनियल डे लियोन

55

जावा 8 अहस्ताक्षरित रूपांतरण द्वारा Byte.toUnsignedIntबदलने के byteलिए प्रदान करता है int। ओरेकल की JDK में इसे केवल return ((int) x) & 0xff;इसलिए लागू किया गया है क्योंकि हॉटस्पॉट पहले से ही समझता है कि इस पैटर्न को कैसे ऑप्टिमाइज़ किया जाए, लेकिन इसे दूसरे वीएम पर इंट्रेंस किया जा सकता है। इससे भी महत्वपूर्ण बात यह है कि कॉल करने के लिए किसी पूर्व ज्ञान की आवश्यकता toUnsignedInt(foo)नहीं है।

कुल में, जावा 8 परिवर्तित करने के लिए तरीके प्रदान byteऔर shortअहस्ताक्षरित के लिए intऔर long, और intअहस्ताक्षरित के लिए longbyteअहस्ताक्षरित shortमें बदलने की विधि जानबूझकर छोड़ी गई थी क्योंकि जेवीएम केवल intऔर longफिर भी अंकगणित प्रदान करता है।

इंट को वापस बाइट में बदलने के लिए, बस एक कास्ट का उपयोग करें (byte)someInt:। परिणामी संकरी आदिम रूपांतरण सभी लेकिन अंतिम 8 बिट्स को छोड़ देगा।


7

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

int signed = -119;  // 11111111 11111111 11111111 10001001

/**
 * Use unsigned right shift operator to drop unset bits in positions 8-31
 */
int psuedoUnsigned = (signed << 24) >>> 24;  // 00000000 00000000 00000000 10001001 -> 137 base 10

/** 
 * Convert back to signed by using the sign-extension properties of the right shift operator
 */
int backToSigned = (psuedoUnsigned << 24) >> 24; // back to original bit pattern

http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html

यदि intआधार प्रकार के अलावा किसी अन्य चीज का उपयोग कर रहे हैं , तो आपको स्पष्ट रूप से शिफ्ट राशि को समायोजित करने की आवश्यकता होगी: http://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html

इसके अलावा, ध्यान रखें कि आप byteप्रकार का उपयोग नहीं कर सकते हैं , ऐसा करने से अन्य उत्तरदाताओं द्वारा उल्लिखित मूल्य पर हस्ताक्षर किए जाएंगे। एक 8-बिट अहस्ताक्षरित मूल्य का प्रतिनिधित्व करने के लिए आप जिस छोटे से आदिम प्रकार का उपयोग कर सकते हैं वह एक होगा short


3

Integer.toString(size)अपने पूर्णांक के चार प्रतिनिधित्व में कॉल धर्मान्तरित, चार अर्थात् '5'ASCII प्रतिनिधित्व कि चरित्र का मूल्य 65 है।

आपको Integer.parseIntमूल पूर्ण मान वापस पाने के लिए स्ट्रिंग को पूर्णांक मान पर वापस भेजने की आवश्यकता है, जैसे कि उपयोग करके ।

एक निचली पंक्ति के रूप में, एक हस्ताक्षरित / अहस्ताक्षरित रूपांतरण के लिए, Stringतस्वीर से बाहर निकलना और @JB के अनुसार बिट हेरफेर का उपयोग करना सबसे अच्छा है।


तो इस तरह? (अभी भी यहां 65 हो रहे हैं)String sizeStr = Integer.toString(size); int sizeInt = Integer.parseInt(sizeStr); byte binaryByte = Byte.valueOf((byte) sizeInt);
डार्कस्की

@ नईफेक, मैंने अपना उत्तर ठीक वैसे ही अपडेट किया जैसे आप अपनी टिप्पणी लिख रहे थे :-)
पेटर तोर्क

ठीक है धन्यवाद! किसी कारण से यह अभी भी 65 प्रिंट करता है। इसका क्या मतलब है? यदि यह सिर्फ 65 दिखाता है, तो वास्तव में बाइट में क्या संग्रहीत किया जा रहा है, तो मुझे नहीं मिलता है। कृपया मेरे प्रश्न की जाँच करें, मैंने इसे संपादित किया और स्ट्रिंग्स रूपांतरण के बारे में एक खंड जोड़ा :) :)
darksky

@Nayefc, फिर से, पाठ में शामिल वर्णोंString.getBytes() के ASCII मानों को जन्म देता है, अंकों के संख्यात्मक मानों को नहीं। जैसा कि मैंने ऊपर संकेत दिया है, आपको स्ट्रिंग को एक संख्यात्मक मान में पार्स करने की आवश्यकता है ।
पेटर तोर्क

1
@Nayefc, इसलिए यह वास्तव में एक अलग सवाल है। और AFAIS को यह काम करना चाहिए। रूपांतरण के वास्तविक इनपुट और आउटपुट और केस को पुन: पेश करने के लिए पूर्ण कोड सहित एक नया प्रश्न बनाएं।
पेटर तोर्क

3

समाधान ठीक काम करता है (धन्यवाद!), लेकिन अगर आप कास्टिंग से बचना चाहते हैं और JDK में निम्न स्तर के काम को छोड़ना चाहते हैं, तो आप अपने इंट को लिखने के लिए DataOutputStream का उपयोग कर सकते हैं और उन्हें वापस पढ़ने के लिए एक DataInputStream लिख सकते हैं। बाइट्स तब:

इंट्री को बाइनरी बाइट्स में परिवर्तित करने के लिए;

ByteArrayOutputStream bos = new ByteArrayOutputStream();
DataOutputStream dos = new DataOutputStream(bos);
int val = 250;
dos.write(byteVal);
...
dos.flush();

उन्हें वापस पढ़ना:

// important to use a (non-Unicode!) encoding like US_ASCII or ISO-8859-1,
// i.e., one that uses one byte per character
ByteArrayInputStream bis = new ByteArrayInputStream(
   bos.toString("ISO-8859-1").getBytes("ISO-8859-1"));
DataInputStream dis = new DataInputStream(bis);
int byteVal = dis.readUnsignedByte();

Esp। बाइनरी डेटा प्रारूपों (जैसे फ्लैट संदेश प्रारूप आदि) से निपटने के लिए उपयोगी


3

सिवाय char, जावा में हर दूसरे संख्यात्मक डेटा प्रकार पर हस्ताक्षर किए गए हैं।

जैसा कि पिछले उत्तर में कहा गया था, आप किसी andऑपरेशन को अंजाम देकर बिना मूल्य के प्राप्त कर सकते हैं 0xFF। इस उत्तर में, मैं यह बताने जा रहा हूं कि यह कैसे होता है।

int i = 234;
byte b = (byte) i;
System.out.println(b);  // -22

int i2 = b & 0xFF;      
// This is like casting b to int and perform and operation with 0xFF

System.out.println(i2); // 234

यदि आपकी मशीन 32-बिट है, तो intमानों को संग्रहीत करने के लिए डेटा प्रकार को 32-बिट की आवश्यकता होती है। byteकेवल 8-बिट की जरूरत है।

intचर iके रूप में (एक 32-बिट पूर्णांक के रूप में) इस प्रकार स्मृति में प्रतिनिधित्व किया है।

0{24}11101010

तब byteचर bको निम्न के रूप में दर्शाया जाता है:

11101010

जैसा कि byteअहस्ताक्षरित हैं, यह मान दर्शाता है -22। (स्मृति में नकारात्मक पूर्णांक का प्रतिनिधित्व करने के तरीके के बारे में अधिक जानने के लिए 2 के पूरक की खोज करें)

फिर यदि आप intइसे डालते हैं, तब भी यह होगा -22क्योंकि कास्टिंग एक संख्या का संकेत सुरक्षित रखता है।

1{24}11101010

के साथ प्रदर्शन आपरेशन के कलाकारों का 32-bitमूल्य ।band0xFF

 1{24}11101010 & 0{24}11111111
=0{24}11101010

फिर आपको 234जवाब के रूप में मिलता है ।


1

बिग बाइट के साथ बाइट्स और अहस्ताक्षरित पूर्णांक संभालना:

byte[] b = ...                    // your integer in big-endian
BigInteger ui = new BigInteger(b) // let BigInteger do the work
int i = ui.intValue()             // unsigned value assigned to i

1

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

https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3.3 एक इंटीग्रल टाइप टी पर हस्ताक्षर किए गए पूर्णांक का एक संकीर्ण रूपांतरण टी केवल सभी को छोड़ देता है लेकिन n निम्नतम ऑर्डर बिट्स, जहां n टाइप टी का प्रतिनिधित्व करने के लिए उपयोग की जाने वाली बिट्स की संख्या है। संख्यात्मक मान की परिमाण के बारे में जानकारी के संभावित नुकसान के अलावा, इससे इनपुट मूल्य के संकेत से भिन्न होने के परिणामस्वरूप परिणाम का संकेत हो सकता है। ।

आप यह सुनिश्चित कर सकते हैं कि एक बाइट एक अभिन्न प्रकार है क्योंकि यह जावा डॉक https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html बाइट कहता है : बाइट डेटा प्रकार 8-बिट पर हस्ताक्षरित दो का है पूर्णांक पूरक।

तो एक पूर्णांक (32 बिट्स) को बाइट (8 बिट्स) में डालने के मामले में, आप बस उस पूर्णांक के अंतिम (कम से कम 8 बिट्स) को दिए गए बाइट वेरिएबल को कॉपी करते हैं।

int a = 128;
byte b = (byte)a; // Last 8 bits gets copied
System.out.println(b);  // -128

कहानी के दूसरे भाग में शामिल है कि जावा यूनरी और बाइनरी ऑपरेटर ऑपरेशंस को कैसे बढ़ावा देते हैं। https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.6.2.2 या तो या दोनों ऑपरेंड को निर्दिष्ट करने के लिए रूपांतरित करने के लिए आदिम रूपांतरण (.15.1.2) को लागू किया जाता है निम्नलिखित नियमों द्वारा:

यदि या तो ऑपरेंड डबल का है, तो दूसरा डबल में बदल जाता है।

अन्यथा, यदि ऑपरेंड या तो फ्लोट का है, तो दूसरा फ्लोट में बदल जाता है।

अन्यथा, यदि या तो ऑपरेंड प्रकार का लंबा है, तो दूसरा लंबे में परिवर्तित हो जाता है।

अन्यथा, दोनों ऑपरेंड को int टाइप करने के लिए कनवर्ट किया जाता है।

निश्चिंत रहें, यदि आप अभिन्न प्रकार के साथ काम कर रहे हैं int और / या कम यह int को बढ़ावा दिया जाएगा।

// byte b(0x80) gets promoted to int (0xFF80) by the & operator and then
// 0xFF80 & 0xFF (0xFF translates to 0x00FF) bitwise operation yields 
// 0x0080
a = b & 0xFF;
System.out.println(a); // 128

मैंने अपना सिर भी इधर उधर कर दिया :)। Rgettman द्वारा यहाँ इसके लिए एक अच्छा जवाब है। जावा में बिटवाइज ऑपरेटर्स केवल पूर्णांक और लंबे समय के लिए?


0

यदि आप आदिम आवरण वर्ग का उपयोग करना चाहते हैं, तो यह काम करेगा, लेकिन सभी जावा प्रकार डिफ़ॉल्ट रूप से हस्ताक्षरित हैं।

public static void main(String[] args) {
    Integer i=5;
    Byte b = Byte.valueOf(i+""); //converts i to String and calls Byte.valueOf()
    System.out.println(b);
    System.out.println(Integer.valueOf(b));
}

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