जावा का उपयोग करके एक हेक्स डंप के स्ट्रिंग प्रतिनिधित्व को बाइट सरणी में बदलें?


372

मैं एक लंबी स्ट्रिंग (एक डंप से) को बदलने का एक रास्ता खोज रहा हूं, जो हेक्स मूल्यों को बाइट सरणी में दर्शाता है।

मैं इसे उस व्यक्ति की तुलना में बेहतर नहीं बना सकता था जिसने यहाँ एक ही प्रश्न पोस्ट किया हो

लेकिन इसे मूल रखने के लिए, मैं इसे अपने तरीके से उद्धृत करूंगा: मान लीजिए कि मेरे पास एक स्ट्रिंग है "00A0BF"जिसे मैं व्याख्या करना चाहूंगा

byte[] {0x00,0xA0,0xBf}

मुझे क्या करना चाहिए?

मैं एक जावा नौसिखिया हूं और BigIntegerअग्रणी हेक्स जीरो के लिए उपयोग कर रहा हूं और देख रहा हूं । लेकिन मुझे लगता है कि यह बदसूरत है और मुझे यकीन है कि मैं कुछ सरल याद कर रहा हूं।


यह भी देखें stackoverflow.com/questions/9655181/...
flow2k

मैंने BigInteger यहां पर वकालत की है
जॉन मैकक्लेन

FWIW String.getBytes()काम नहीं करेगा जैसे आपको लगता है कि यह हो सकता है। इसे कठिन तरीके से सीखना था। if ("FF".getBytes() != "ff".getBytes()) { System.out.println("Try again"); }
tir38

जवाबों:


636

यहाँ एक समाधान है जो मुझे लगता है कि अब तक किसी भी पोस्ट से बेहतर है:

public static byte[] hexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

यह क्यों एक सुधार है कारण:

  • प्रमुख शून्य (बिगइंटर के विपरीत) के साथ सुरक्षित और नकारात्मक बाइट मूल्यों के साथ (बाइट.परसेबीट के विपरीत)

  • स्ट्रिंग को एक में परिवर्तित नहीं करता है char[], या हर एक बाइट के लिए स्ट्रिंगबर्ल और स्ट्रिंग ऑब्जेक्ट नहीं बनाता है।

  • कोई लाइब्रेरी निर्भरता जो उपलब्ध नहीं हो सकती है

assertयदि तर्क सुरक्षित होने के लिए ज्ञात नहीं है, तो अपवाद या अपवाद के माध्यम से तर्क जाँच को जोड़ने के लिए स्वतंत्र महसूस करें ।


2
क्या आप एक उदाहरण दे सकते हैं जो गलत तरीके से डिकोड किया गया है, या समझाएं कि यह कैसे गलत है?
डेव एल।

5
यह स्ट्रिंग "0" के लिए काम नहीं करता है। यह एक java.lang.StringIndexOutOfBoundsException फेंकता है
Ovdsrn

49
"0" वैध इनपुट नहीं है। बाइट्स को दो हेक्सिडेसिमल अंकों की आवश्यकता होती है। उत्तर के रूप में, "तर्क जाँच जोड़ने के लिए स्वतंत्र महसूस करें ... यदि तर्क सुरक्षित नहीं है।"
डेव एल।

12
javax.xml.bind.DatatypeConverter.parseHexBinary (hexString) मेरे माइक्रो परीक्षणों में उपरोक्त समाधान की तुलना में लगभग 20% तेज लगता है (जो कुछ भी उनके लायक है), साथ ही अवैध इनपुट (जैसे "जीजी" पर सही ढंग से अपवादों को फेंक देते हैं। एक वैध हेक्सस्ट्रिंग नहीं है, लेकिन प्रस्तावित के रूप में समाधान का उपयोग करके -77 वापस आ जाएगा)।
ट्रेवर फ्रीमैन

6
@DaedalusAlpha यह आपके संदर्भ पर निर्भर करता है, लेकिन आमतौर पर मुझे ऐसी चीजों के साथ तेजी से और जोर से विफल होना बेहतर लगता है ताकि आप चुपचाप गलत डेटा लौटने के बजाय अपनी मान्यताओं को ठीक कर सकें।
डेव एल।

331

एक-लाइनर्स:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

चेतावनी :

  • जावा 9 आरा में यह (डिफ़ॉल्ट) java.se रूट सेट का हिस्सा नहीं है, इसलिए इसका परिणाम ClassNotFoundException में होगा जब तक कि आप निर्दिष्ट नहीं करते हैं --add-मॉड्यूल java.se.ee (@ के लिए धन्यवाद eckes)
  • एंड्रॉइड पर उपलब्ध नहीं है ( Fabianध्यान दें कि इसके लिए धन्यवाद ), लेकिन आप स्रोत कोड ले सकते हैं यदि आपके सिस्टम में javax.xmlकिसी कारण से कमी हो । Bert Regelinkस्रोत निकालने के लिए @ का धन्यवाद ।

14
IMHO यह स्वीकृत / शीर्ष उत्तर होना चाहिए क्योंकि यह छोटा और साफ है (@ डेवले के उत्तर के विपरीत) और इसके लिए किसी बाहरी परिवाद (जैसे कि स्कैफ़मैन के उत्तर) की आवश्यकता नहीं है। इसके अलावा, साइकिल को सुदृढ़ करने के बारे में एक पहना मजाक दर्ज करें>
प्रिदु नीमरे

9
उदाहरण के लिए datatypeconverter वर्ग Android में उपलब्ध नहीं है।
फेबियन

4
चेतावनी: जावा 9 Jigsaw में यह (डिफ़ॉल्ट) का भाग नहीं है java.seजड़ सेट इसलिए यह एक में परिणाम होगा ClassNotFoundException, जब तक कि आपके द्वारा निर्दिष्ट--add-modules java.se.ee
Eckes

2
@dantebarba मुझे लगता है कि javax.xml.bind.DatatypeConverterपहले से ही Base64 डेटा को एन्कोडिंग / डिकोड करने के लिए एक विधि उपलब्ध है। देखें parseBase64Binary()और printBase64Binary()
ड्रैगशॉट जूल

2
मुद्दों के साथ जोड़ने के लिए DataTypeConverter, जावा एसई 11 ने जेएएक्सबी एपीआई को पूरी तरह से हटा दिया है और अब केवल जावा ईई के साथ शामिल किया गया है। आप इसे मावेन निर्भरता के रूप में भी जोड़ सकते हैं, जैसा कि यहां सुझाया गया है: stackoverflow.com/a/43574427/7347751
डेविड मॉर्डिगल

79

कॉमन्स-कोडेक में हेक्स क्लास को आपके लिए ऐसा करना चाहिए।

http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF

6
यह भी अच्छा लगता है। देखें org.apache.commons.codec.binary.Hex.decodeHex ()
डेव एल।

यह दिलचस्प था। लेकिन मैंने उनके समाधान का पालन करना मुश्किल पाया। क्या यह आपके द्वारा प्रस्तावित किए गए (चार्ट की संख्या के लिए जाँच के अलावा) कोई लाभ है?
1

38

अब आप इसे पूरा करने के लिए बेसइंकोडिंग का उपयोग कर सकते हैं guava

BaseEncoding.base16().decode(string);

इसका उल्टा उपयोग करने के लिए

BaseEncoding.base16().encode(bytes);

27

वास्तव में, मुझे लगता है कि BigInteger समाधान बहुत अच्छा है:

new BigInteger("00A0BF", 16).toByteArray();

संपादित करें: प्रमुख शून्य के लिए सुरक्षित नहीं , जैसा कि पोस्टर ने नोट किया है।


मैंने भी शुरू में यही सोचा था। और इसे प्रलेखित करने के लिए धन्यवाद - मैं बस सोच रहा था कि मुझे क्या करना चाहिए ... हालांकि कुछ अजीब चीजें हुईं जो मुझे वास्तव में समझ में नहीं आईं - जैसे कुछ प्रमुख 0x00 को छोड़ दें और 156 बाइट स्ट्रिंग में 1 बाइट के क्रम को मिलाएं। साथ खेल रहा था।
rafraf

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

1
हाँ, जैसे ही मैंने यह कहा, मुझे विश्वास नहीं हुआ या तो :) मैं बिगइंटर से बाइट सरणी की तुलना में mmyers'fromHexString के साथ और आक्रामक स्ट्रिंग के खिलाफ (0x00 के साथ) - वे समान थे। "मिक्स अप" हुआ, लेकिन यह कुछ और हो सकता था। मैं कल और अधिक बारीकी से
देखूंगा

3
BigInteger के साथ मुद्दा यह है कि "साइन बिट" होना चाहिए। यदि अग्रणी बाइट में उच्च बिट सेट है तो परिणामी बाइट सरणी में 1 स्थिति में अतिरिक्त 0 है। लेकिन फिर भी +1।
ग्रे

25

एक-लाइनर्स:

import javax.xml.bind.DatatypeConverter;

public static String toHexString(byte[] array) {
    return DatatypeConverter.printHexBinary(array);
}

public static byte[] toByteArray(String s) {
    return DatatypeConverter.parseHexBinary(s);
}

FractalizeR से वन-लाइनर्स के पीछे वास्तविक कोड में रुचि रखने वालों के लिए (मुझे चाहिए था कि चूंकि javax.xml.bind Android (डिफ़ॉल्ट रूप से) के लिए उपलब्ध नहीं है), यह com.sun.xml.ternal.bind से आता है । डेटाटाइपकंट्रीइम्प्ल.जावा :

public byte[] parseHexBinary(String s) {
    final int len = s.length();

    // "111" is not a valid hex encoding.
    if( len%2 != 0 )
        throw new IllegalArgumentException("hexBinary needs to be even-length: "+s);

    byte[] out = new byte[len/2];

    for( int i=0; i<len; i+=2 ) {
        int h = hexToBin(s.charAt(i  ));
        int l = hexToBin(s.charAt(i+1));
        if( h==-1 || l==-1 )
            throw new IllegalArgumentException("contains illegal character for hexBinary: "+s);

        out[i/2] = (byte)(h*16+l);
    }

    return out;
}

private static int hexToBin( char ch ) {
    if( '0'<=ch && ch<='9' )    return ch-'0';
    if( 'A'<=ch && ch<='F' )    return ch-'A'+10;
    if( 'a'<=ch && ch<='f' )    return ch-'a'+10;
    return -1;
}

private static final char[] hexCode = "0123456789ABCDEF".toCharArray();

public String printHexBinary(byte[] data) {
    StringBuilder r = new StringBuilder(data.length*2);
    for ( byte b : data) {
        r.append(hexCode[(b >> 4) & 0xF]);
        r.append(hexCode[(b & 0xF)]);
    }
    return r.toString();
}

3
DatatypeConverter जावा 9 में भी डिफ़ॉल्ट रूप से उपलब्ध नहीं है। खतरनाक चीज कोड का उपयोग कर कोड है जो जावा 1.8 या उससे पहले (जावा 9 स्रोत सेटिंग्स के साथ पहले) के तहत संकलित करेगा, लेकिन जावा 9 के तहत "-add-मॉड्यूल java.se.ee" के बिना रनटाइम अपवाद प्राप्त करें।
स्टीफन एम-स्ट्राइक-

24

HexBinaryAdapterमार्शल करने के लिए क्षमता और के बीच unmarshal प्रदान करता है Stringऔर byte[]

import javax.xml.bind.annotation.adapters.HexBinaryAdapter;

public byte[] hexToBytes(String hexString) {
     HexBinaryAdapter adapter = new HexBinaryAdapter();
     byte[] bytes = adapter.unmarshal(hexString);
     return bytes;
}

यह सिर्फ एक उदाहरण है जो मैंने टाइप किया है ... मैं वास्तव में इसका उपयोग करता हूं और इसे उपयोग करने के लिए एक अलग विधि बनाने की आवश्यकता नहीं है।


5
यह तभी काम करता है जब इनपुट स्ट्रिंग (हेक्सस्ट्रिंग) में वर्णों की संख्या समान हो। अन्यथा: थ्रेड में अपवाद "मुख्य" java.lang.IllegalArgumentException: हेक्सबिनल को समान-लंबाई की आवश्यकता है:
Ovdsrn

3
ओह, यह इंगित करने के लिए धन्यवाद। एक उपयोगकर्ता को वास्तव में वर्णों की एक विषम संख्या नहीं होनी चाहिए क्योंकि बाइट सरणी को {0x00,0xA0,0xBf} के रूप में दर्शाया गया है। प्रत्येक बाइट में दो हेक्स अंक या नीबल्स होते हैं। इसलिए किसी भी संख्या में बाइट्स में हमेशा सम संख्या वाले वर्ण होने चाहिए। इस उल्लेख के लिए धन्यवाद।
GrkEngineer

8
आप HexBinaryAdapter (जो बदले में DatatypeConverter को कॉल करते हैं) का उपयोग करने के बजाय सीधे java.xml.bind.DatatypeConverter.parseHexBinary (hexString) का उपयोग कर सकते हैं। इस तरह आपको एडेप्टर इंस्टेंस ऑब्जेक्ट बनाने की ज़रूरत नहीं है (क्योंकि डेटाटाइप कॉन्टेक् ट विधियां स्थिर हैं)।
ट्रेवर फ्रीमैन

javax.xml.bind। * जावा 9 में अब उपलब्ध नहीं है। खतरनाक चीज कोड का उपयोग करके कोड जावा 1.8 या इससे पहले (जावा 9 पहले स्रोत सेटिंग्स के साथ) के तहत संकलित करेगी, लेकिन जावा 9 के तहत चलने वाला एक रनटाइम अपवाद प्राप्त करें
स्टीफन एम-स्ट्राइक-

15

यहाँ एक विधि है जो वास्तव में काम करती है (पिछले कई अर्ध-सही उत्तरों के आधार पर):

private static byte[] fromHexString(final String encoded) {
    if ((encoded.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[encoded.length()/2];
    final char enc[] = encoded.toCharArray();
    for (int i = 0; i < enc.length; i += 2) {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[i]).append(enc[i + 1]);
        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

एकमात्र संभावित मुद्दा जो मैं देख सकता हूं कि क्या इनपुट स्ट्रिंग बहुत लंबी है; toCharArray () कॉलिंग स्ट्रिंग के आंतरिक सरणी की एक प्रतिलिपि बनाता है।

संपादित करें: ओह, और वैसे, जावा में बाइट्स पर हस्ताक्षर किए जाते हैं, इसलिए आपका इनपुट स्ट्रिंग [0, -96, -65] के बजाय [0, 160, 191] में परिवर्तित हो जाता है। लेकिन आप शायद पहले से ही जानते थे।


1
धन्यवाद माइकल - तुम एक जीवन रक्षक हो! एक ब्लैकबेरी प्रोजेक्ट पर काम करना और एक बाइट के स्ट्रिंग प्रतिनिधित्व को बाइट में बदलने की कोशिश करना ... रिम के "बाइट.परसे बाइट (बाइटस्ट्रिंग, 16)" विधि का उपयोग करना। नंबरफ़ॉर्मैटएक्सपेप्शन को फेंकना। क्यों पता लगाने के लिए समय बिताया। आपके सुझाव "Integer.praseInt ()" ने किया। एक बार फिर धन्यवाद!!
बोनांजाड्राइवर

12

एंड्रॉइड में, यदि आप हेक्स के साथ काम कर रहे हैं, तो आप ओकिओ की कोशिश कर सकते हैं ।

सरल उपयोग:

byte[] bytes = ByteString.decodeHex("c000060000").toByteArray();

और परिणाम होगा

[-64, 0, 6, 0, 0]

मैंने कई अलग-अलग तरीकों का परीक्षण किया है लेकिन यह कम से कम दो बार उपवास है!
poby

5

BigInteger()Java.math से विधि बहुत धीमे और recommandable नहीं है।

Integer.parseInt(HEXString, 16)

डिजिट / इंटेगर में कनवर्ट किए बिना कुछ वर्णों के साथ समस्या हो सकती है

एक अच्छी तरह से काम करने की विधि:

Integer.decode("0xXX") .byteValue()

समारोह:

public static byte[] HexStringToByteArray(String s) {
    byte data[] = new byte[s.length()/2];
    for(int i=0;i < s.length();i+=2) {
        data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
    }
    return data;
}

फन, गुड लक


4

संपादित करें: जैसा कि @ खरीदारों द्वारा बताया गया है, यह विधि इनपुट पर काम नहीं करती है जिसमें उच्च बिट सेट ("80" - "एफएफ") के साथ बाइट्स के अनुरूप सब्सट्रेट होते हैं। विवरण बग आईडी पर है: 6259307 Byte.parseByte एसडीके प्रलेखन में विज्ञापित के रूप में काम नहीं कर रहा है

public static final byte[] fromHexString(final String s) {
    byte[] arr = new byte[s.length()/2];
    for ( int start = 0; start < s.length(); start += 2 )
    {
        String thisByte = s.substring(start, start+2);
        arr[start/2] = Byte.parseByte(thisByte, 16);
    }
    return arr;
}

1
बंद करें, लेकिन यह विधि दिए गए इनपुट "00A0BBF" पर विफल है। Bugs.sun.com/bugdatabase/view_bug.do?bug_id=6259307 देखें ।
माइकल मायर्स

1
इसके अलावा अजीब तरह से यह "9 सी" के साथ सौदा नहीं करता है
रफ़्र

1
@ खरीदार: वाह। यह अच्छा नहीं है। वें भ्रम के लिए क्षमा करें। @ravigad: 9C में एक ही समस्या है क्योंकि इस मामले में उच्च बिट सेट है।
ब्लेयर कॉनरैड

(बाइट) Short.parseShort (यह बाइट, 16) उस समस्या को हल करता है
Jamey Hicks

3

क्या यह मूल्य के लिए है, यहां एक और संस्करण है जो अजीब लंबाई के तार का समर्थन करता है, बिना स्ट्रिंग समवर्ती का सहारा लेता है।

public static byte[] hexStringToByteArray(String input) {
    int len = input.length();

    if (len == 0) {
        return new byte[] {};
    }

    byte[] data;
    int startIdx;
    if (len % 2 != 0) {
        data = new byte[(len / 2) + 1];
        data[0] = (byte) Character.digit(input.charAt(0), 16);
        startIdx = 1;
    } else {
        data = new byte[len / 2];
        startIdx = 0;
    }

    for (int i = startIdx; i < len; i += 2) {
        data[(i + 1) / 2] = (byte) ((Character.digit(input.charAt(i), 16) << 4)
                + Character.digit(input.charAt(i+1), 16));
    }
    return data;
}

2

मैंने हमेशा एक विधि का उपयोग किया है

public static final byte[] fromHexString(final String s) {
    String[] v = s.split(" ");
    byte[] arr = new byte[v.length];
    int i = 0;
    for(String val: v) {
        arr[i++] =  Integer.decode("0x" + val).byteValue();

    }
    return arr;
}

यह विधि अंतरिक्ष सीमांकित हेक्स मानों पर विभाजित करती है, लेकिन इसे दो वर्णों के समूह में किसी अन्य मानदंड पर स्ट्रिंग को विभाजित करना मुश्किल नहीं होगा।


स्ट्रिंग संघनन अनावश्यक है। बस Integer.valueOf (वैल, 16) का उपयोग करें।
माइकल मायर्स

मैंने पहले की तरह मूलांक के रूपांतरणों का उपयोग करने की कोशिश की है और मैंने
पीएफआरंजा

धन्यवाद - अजीब तरह से यह इस स्ट्रिंग के साथ ठीक काम करता है: "9C001C" या "001C21" और इसके साथ विफल रहता है: "9C001C21" थ्रेड में अपवाद "मुख्य" java.lang.NumberFormatException: इनपुट स्ट्रिंग के लिए: java.lang पर "9C001C21"। NumberFormatException.forInputString (अज्ञात स्रोत)
rafraf

(इस मामले में Byte/ की तुलना में अधिक अजीब नहीं है byte: उच्चतम बिट के बिना अग्रणी -)
ग्रेबियर

2

मुझे Character.digit समाधान पसंद है, लेकिन यहां बताया गया है कि मैंने इसे कैसे हल किया

public byte[] hex2ByteArray( String hexString ) {
    String hexVal = "0123456789ABCDEF";
    byte[] out = new byte[hexString.length() / 2];

    int n = hexString.length();

    for( int i = 0; i < n; i += 2 ) {
        //make a bit representation in an int of the hex value 
        int hn = hexVal.indexOf( hexString.charAt( i ) );
        int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );

        //now just shift the high order nibble and add them together
        out[i/2] = (byte)( ( hn << 4 ) | ln );
    }

    return out;
}

2

बर्ट रेगेलिंक द्वारा प्रस्तुत कोड बस काम नहीं करता है। निम्नलिखित आज़माएँ:

import javax.xml.bind.DatatypeConverter;
import java.io.*;

public class Test
{  
    @Test
    public void testObjectStreams( ) throws IOException, ClassNotFoundException
    {     
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(baos);

            String stringTest = "TEST";
            oos.writeObject( stringTest );

            oos.close();
            baos.close();

            byte[] bytes = baos.toByteArray();
            String hexString = DatatypeConverter.printHexBinary( bytes);
            byte[] reconvertedBytes = DatatypeConverter.parseHexBinary(hexString);

            assertArrayEquals( bytes, reconvertedBytes );

            ByteArrayInputStream bais = new ByteArrayInputStream(reconvertedBytes);
            ObjectInputStream ois = new ObjectInputStream(bais);

            String readString = (String) ois.readObject();

            assertEquals( stringTest, readString);
        }
    }

2
यह वास्तव में एक अलग समस्या है, और संभवतः दूसरे धागे पर है।
शॉन कॉफ़ी

1

मुझे लगा कि कर्नेल पैनिक का समाधान मेरे लिए सबसे उपयोगी है, लेकिन अगर हेक्स स्ट्रिंग एक विषम संख्या थी, तो समस्याओं में भाग गया। इसे इस तरह हल किया:

boolean isOdd(int value)
{
    return (value & 0x01) !=0;
}

private int hexToByte(byte[] out, int value)
{
    String hexVal = "0123456789ABCDEF"; 
    String hexValL = "0123456789abcdef";
    String st = Integer.toHexString(value);
    int len = st.length();
    if (isOdd(len))
        {
        len+=1; // need length to be an even number.
        st = ("0" + st);  // make it an even number of chars
        }
    out[0]=(byte)(len/2);
    for (int i =0;i<len;i+=2)
    {
        int hh = hexVal.indexOf(st.charAt(i));
            if (hh == -1)  hh = hexValL.indexOf(st.charAt(i));
        int lh = hexVal.indexOf(st.charAt(i+1));
            if (lh == -1)  lh = hexValL.indexOf(st.charAt(i+1));
        out[(i/2)+1] = (byte)((hh << 4)|lh);
    }
    return (len/2)+1;
}

मैं एक सरणी में कई हेक्स संख्या जोड़ रहा हूं, इसलिए मैं जिस सरणी का उपयोग कर रहा हूं, उसके संदर्भ को पास करता हूं, और मुझे अगले हेक्स नंबर की सापेक्ष स्थिति को परिवर्तित करने और वापस करने की आवश्यकता है। तो अंतिम बाइट सरणी में हेक्स जोड़े की संख्या [0] है, [1 ...] हेक्स जोड़े, फिर जोड़े की संख्या ...


1

ऑप वोट किए गए समाधान के आधार पर, निम्नलिखित थोड़ा अधिक कुशल होना चाहिए:

  public static byte [] hexStringToByteArray (final String s) {
    if (s == null || (s.length () % 2) == 1)
      throw new IllegalArgumentException ();
    final char [] chars = s.toCharArray ();
    final int len = chars.length;
    final byte [] data = new byte [len / 2];
    for (int i = 0; i < len; i += 2) {
      data[i / 2] = (byte) ((Character.digit (chars[i], 16) << 4) + Character.digit (chars[i + 1], 16));
    }
    return data;
  }

क्योंकि: एक चार सरणी में प्रारंभिक रूपांतरण चार्ज में लंबाई की जांच करता है


1

यदि आपके पास अपनी कोडिंग शैली के रूप में जावा 8 स्ट्रीम के लिए प्राथमिकता है, तो यह सिर्फ JDK प्राइमेटिव का उपयोग करके प्राप्त किया जा सकता है।

String hex = "0001027f80fdfeff";

byte[] converted = IntStream.range(0, hex.length() / 2)
    .map(i -> Character.digit(hex.charAt(i * 2), 16) << 4 | Character.digit(hex.charAt((i * 2) + 1), 16))
    .collect(ByteArrayOutputStream::new,
             ByteArrayOutputStream::write,
             (s1, s2) -> s1.write(s2.toByteArray(), 0, s2.size()))
    .toByteArray();

, 0, s2.size()अगर आप को पकड़ने कोई आपत्ति नहीं है कलेक्टर जोड़ने के फ़ंक्शन में पैरामीटर छोड़ा जा सकता है IOException


0
public static byte[] hex2ba(String sHex) throws Hex2baException {
    if (1==sHex.length()%2) {
        throw(new Hex2baException("Hex string need even number of chars"));
    }

    byte[] ba = new byte[sHex.length()/2];
    for (int i=0;i<sHex.length()/2;i++) {
        ba[i] = (Integer.decode(
                "0x"+sHex.substring(i*2, (i+1)*2))).byteValue();
    }
    return ba;
}

0

मेरा औपचारिक समाधान:

/**
 * Decodes a hexadecimally encoded binary string.
 * <p>
 * Note that this function does <em>NOT</em> convert a hexadecimal number to a
 * binary number.
 *
 * @param hex Hexadecimal representation of data.
 * @return The byte[] representation of the given data.
 * @throws NumberFormatException If the hexadecimal input string is of odd
 * length or invalid hexadecimal string.
 */
public static byte[] hex2bin(String hex) throws NumberFormatException {
    if (hex.length() % 2 > 0) {
        throw new NumberFormatException("Hexadecimal input string must have an even length.");
    }
    byte[] r = new byte[hex.length() / 2];
    for (int i = hex.length(); i > 0;) {
        r[i / 2 - 1] = (byte) (digit(hex.charAt(--i)) | (digit(hex.charAt(--i)) << 4));
    }
    return r;
}

private static int digit(char ch) {
    int r = Character.digit(ch, 16);
    if (r < 0) {
        throw new NumberFormatException("Invalid hexadecimal string: " + ch);
    }
    return r;
}

PHP hex2bin () फ़ंक्शन की तरह है, लेकिन जावा शैली में।

उदाहरण:

String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"

0

पार्टी के लिए देर हो चुकी है, लेकिन मैंने डेवएल द्वारा ऊपर दिए गए जवाब को एक वर्ग में उलट कार्रवाई के साथ जोड़ दिया है - बस मामले में यह मदद करता है।

public final class HexString {
    private static final char[] digits = "0123456789ABCDEF".toCharArray();

    private HexString() {}

    public static final String fromBytes(final byte[] bytes) {
        final StringBuilder buf = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            buf.append(HexString.digits[(bytes[i] >> 4) & 0x0f]);
            buf.append(HexString.digits[bytes[i] & 0x0f]);
        }
        return buf.toString();
    }

    public static final byte[] toByteArray(final String hexString) {
        if ((hexString.length() % 2) != 0) {
            throw new IllegalArgumentException("Input string must contain an even number of characters");
        }
        final int len = hexString.length();
        final byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
                    + Character.digit(hexString.charAt(i + 1), 16));
        }
        return data;
    }
}

और JUnit परीक्षण वर्ग:

public class TestHexString {

    @Test
    public void test() {
        String[] tests = {"0FA1056D73", "", "00", "0123456789ABCDEF", "FFFFFFFF"};

        for (int i = 0; i < tests.length; i++) {
            String in = tests[i];
            byte[] bytes = HexString.toByteArray(in);
            String out = HexString.fromBytes(bytes);
            System.out.println(in); //DEBUG
            System.out.println(out); //DEBUG
            Assert.assertEquals(in, out);

        }

    }

}

0

मुझे पता है कि यह एक बहुत पुराना धागा है, लेकिन फिर भी मैं अपने पैसे को जोड़ना चाहता हूं।

अगर मुझे द्विआधारी कनवर्टर के लिए एक साधारण हेक्स स्ट्रिंग को कोड करने की आवश्यकता है, तो मैं इसे निम्नानुसार करना चाहूंगा।

public static byte[] hexToBinary(String s){

  /*
   * skipped any input validation code
   */

  byte[] data = new byte[s.length()/2];

  for( int i=0, j=0; 
       i<s.length() && j<data.length; 
       i+=2, j++)
  {
     data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
  }

  return data;
}

0

अब तक सबसे साफ समाधान नहीं है। लेकिन यह मेरे लिए काम करता है और अच्छी तरह से स्वरूपित है:

private String createHexDump(byte[] msg, String description) {
    System.out.println();
    String result = "\n" + description;
    int currentIndex = 0;
    int printedIndex = 0;
    for(int i=0 ; i<msg.length ; i++){
        currentIndex++;
        if(i == 0){
            result += String.format("\n  %04x ", i);
        }
        if(i % 16 == 0 && i != 0){
            result += " | ";
            for(int j=(i-16) ; j<msg.length && j<i ; j++) {
                char characterToAdd = (char) msg[j];
                if (characterToAdd == '\n') {
                    characterToAdd = ' ';
                }
                result += characterToAdd;
                printedIndex++;
            }

            result += String.format("\n  %04x ", i);
        }

        result += String.format("%02x ", msg[i]);
    }

    if(currentIndex - printedIndex > 0){
        int leftOvers = currentIndex - printedIndex;
        for(int i=0 ; i<16-leftOvers ; i++){
            result += "   ";
        }

        result += " | ";

        for(int i=msg.length-leftOvers ; i<msg.length ; i++){
            char characterToAdd = (char) msg[i];
            if (characterToAdd == '\n') {
                characterToAdd = ' ';
            }
            result += characterToAdd;
        }
    }

    result += "\n";

    return result;
}

उत्पादन:

  S -> C
    0000 0b 00 2e 06 4d 6f 72 69 74 7a 53 6f 6d 65 20 54  |  .Heyyy Some T
    0010 43 50 20 73 74 75 66 66 20 49 20 63 61 70 74 75  | CP stuff I captu
    0020 72 65 64 2e 2e 77 65 6c 6c 20 66 6f 72 6d 61 74  | red..well format
    0030 3f                                               | ?

-2

मुझे लगता है कि यह आपके लिए करेगा। मैंने इसे एक समान फ़ंक्शन से एक साथ सिल दिया था जो डेटा को स्ट्रिंग के रूप में लौटाता है:

private static byte[] decode(String encoded) {
    byte result[] = new byte[encoded/2];
    char enc[] = encoded.toUpperCase().toCharArray();
    StringBuffer curr;
    for (int i = 0; i < enc.length; i += 2) {
        curr = new StringBuffer("");
        curr.append(String.valueOf(enc[i]));
        curr.append(String.valueOf(enc[i + 1]));
        result[i] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

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

-2

मेरे लिए यह समाधान था, HEX = "FF01" फिर FF (255) और 01 (01) में विभाजित हो गया

private static byte[] BytesEncode(String encoded) {
    //System.out.println(encoded.length());
    byte result[] = new byte[encoded.length() / 2];
    char enc[] = encoded.toUpperCase().toCharArray();
    String curr = "";
    for (int i = 0; i < encoded.length(); i=i+2) {
        curr = encoded.substring(i,i+2);
        System.out.println(curr);
        if(i==0){
            result[i]=((byte) Integer.parseInt(curr, 16));
        }else{
            result[i/2]=((byte) Integer.parseInt(curr, 16));
        }

    }
    return result;
}

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