जावा में एक बाइट स्ट्रिंग को बाइट सरणी में कैसे बदलें?


649

मेरे पास हेक्स नंबरों से भरा एक बाइट सरणी है और इसे आसान तरीके से प्रिंट करना बहुत व्यर्थ है क्योंकि इसमें बहुत से अप्राप्य तत्व हैं। मुझे इसके रूप में सटीक हेक्सकोड की आवश्यकता है:3a5f771c


12
क्यों न आप इसे पहले आज़माएँ और हमें दिखाएँ कि आपको क्या मिला है। आपके पास खोने के लिए और पाने के लिए कुछ भी नहीं है। इंटेगर के पास एक toHexString(...)तरीका है जो आपकी मदद कर सकता है यदि आप यही चाहते हैं। कोड स्ट्रिंग String.format(...)का उपयोग करके कुछ साफ-सुथरी फॉर्मेटिंग ट्रिक्स भी कर सकते हैं %2x
होल्सक्राफ्ट


"मुझे क्या जरूरत है: 3a5f771c ... के रूप में सटीक हेक्सकोड ..." - आपने एक सटीक फॉर्म मांगा, लेकिन आपने एक सटीक उदाहरण नहीं दिया। आपने जो प्रदान किया है, उस पर चलते हुए, पहले चार बाइट्स को एक स्ट्रिंग में बदलें, फिर स्ट्रिंग को दीर्घवृत्त प्रदान करें।
jww

1
Java 8 में स्ट्रीम की सहायता से, इसे सरल रूप से लागू किया जा सकता है: स्टेटिक स्ट्रिंग byteArrayToHex (बाइट [a) ​​{रिटर्न IntStream.range (0, a.length) .mapToObj (i -> String.format ("% 02x) ", [a (i])) .reduce ((एसीसी, v) -> एसीसी +" "+ v) .get (); }
टिबेट्टी

जवाबों:


900

यहां चर्चा से , और विशेष रूप से इस उत्तर से, यह वह फ़ंक्शन है जो मैं वर्तमान में उपयोग करता हूं:

private static final char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}

मेरे खुद के छोटे बेंचमार्क (एक लाख बाइट्स एक हजार गुना, 256 बाइट्स 10 मिलियन बार) ने इसे किसी भी अन्य विकल्प की तुलना में बहुत तेजी से दिखाया, लंबे समय तक सरणियों पर लगभग आधा समय। उत्तर की तुलना में मैंने इसे लिया, बिटकॉइन ऑप्स पर स्विच करना --- जैसा कि चर्चा में सुझाया गया है --- लंबी सरणियों के लिए समय का लगभग 20% काट दिया। (संपादित करें: जब मैं कहता हूं कि यह विकल्पों की तुलना में तेज है, मेरा मतलब है कि चर्चाओं में पेश किया गया वैकल्पिक कोड। प्रदर्शन कॉमन्स कोडेक के बराबर है, जो बहुत समान कोड का उपयोग करता है।)

जावा 9 कॉम्पैक्ट स्ट्रिंग्स के संबंध में 2k20 संस्करण:

private static final byte[] HEX_ARRAY = "0123456789ABCDEF".toByteArray();
public static String bytesToHex(byte[] bytes) {
    byte[] hexChars = new byte[bytes.length * 2];
    for (int j = 0; j < bytes.length; j++) {
        int v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars, StandardCharsets.UTF_8);
}

266
मुझे सिर्फ javax.xml.bind.DataTypeConverter मिला है , जो मानक वितरण का हिस्सा है। जब आप इस तरह की समस्या से गुज़रते हैं तो यह क्यों नहीं आता है? बहुत से सहायक उपकरण, सहित String printHexBinary(byte[])और byte[] parseHexBinary(String)printHexBinaryहालाँकि, इस उत्तर में फ़ंक्शन की तुलना में बहुत (2x) धीमा है। (मैं स्रोत की जाँच की है, यह एक का उपयोग करता है stringBuilderparseHexBinaryएक सरणी का उपयोग करता है।) वास्तव में, हालांकि, सबसे प्रयोजनों के लिए काफी तेजी से है और आप शायद पहले से ही पास है।
WeWeCouldStealAVan

75
जवाब के लिए +1 चूंकि एंड्रॉइड में डेटा
टाइपकॉर्टर

7
@maybeWeCouldStealAVan: JDK 7 अब खुला स्रोत है। हमें प्रदर्शन में सुधार के लिए एक पैच प्रस्तुत करना चाहिए printHexBinary?
केविनरपे

3
@maybeWeCouldStealAVan क्या आप बता सकते हैं कि यह कैसे काम करता है। मैं अधिकांश भाग के लिए अनुसरण करता हूं, लेकिन कोड का उपयोग करते समय वास्तव में क्या हो रहा है, यह समझना पसंद करता है। धन्यवाद!
jjNford 19

24
javax.xml.bind.DataTypeConverterजावा 11 से हटाया जा रहा है
द इम्पेलर

421

अपाचे कॉमन्स कोडेक पुस्तकालय एक है हेक्स सिर्फ काम के इस प्रकार करने के लिए वर्ग।

import org.apache.commons.codec.binary.Hex;

String foo = "I am a string";
byte[] bytes = foo.getBytes();
System.out.println( Hex.encodeHexString( bytes ) );

12
@ साइटिनस - मेरा डाउनवोट 4 महीने पहले हुआ था इसलिए मैं पूरी तरह से निश्चित नहीं हूं कि मैं क्या सोच रहा था, लेकिन मैं शायद पुस्तकालय के आकार पर आपत्ति कर रहा था। यह कार्यक्रम के भीतर एक छोटा सा कार्य है; इसे करने के लिए परियोजना में इस तरह के भारी पुस्तकालय को जोड़ने की आवश्यकता नहीं है।
आर्टऑफवर्फ

6
@ArtOfWarefare मैं सहमत हूँ, इसलिए import org.apache.commons.codec.*;आप के बजाय कर सकते हैंimport org.apache.commons.codec.binary.Hex;
साइटिनस

12
@ArtOfWarfare मुझे असहमत होना है। केवल भयानक बात यह है कि Apache commons पुस्तकालयों को JRE और JDK के साथ डिफ़ॉल्ट रूप से शामिल नहीं किया गया है। कुछ पुस्तकालय हैं जो बहुत उपयोगी हैं वे वास्तव में डिफ़ॉल्ट रूप से आपके वर्ग पथ पर होने चाहिए, और यह उनमें से एक है।
corsiKa

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

6
या यदि आप BouncyCastle ( org.b Councilycastle: bcprov-jdk15on ) का उपयोग करते हैं, तो आप इस वर्ग का उपयोग कर सकते हैं: org.bouncycastle.util.encoders.Hexइस विधि के साथ:String toHexString(byte[] data)
Guillaume Husta

320

XML बाइंडिंग (JAXB) के लिए जावा आर्किटेक्चरjavax.xml.bind.DatatypeConverter.printHexBinary() का हिस्सा विधि , हेक्स स्ट्रिंग में परिवर्तित करने का एक सुविधाजनक तरीका था । byte[]DatatypeConverterवर्ग भी कई अन्य उपयोगी डेटा हेरफेर तरीकों शामिल थे।

जावा 8 और पूर्व में, JAXB जावा मानक पुस्तकालय का हिस्सा था। यह था पदावनत जावा 9 के साथ और हटाया जावा 11 के साथ अपने स्वयं के पुस्तकालयों में सभी जावा ईई संकुल को स्थानांतरित करने के प्रयास के हिस्से के रूप। यह एक लंबी कहानी है । अब, javax.xml.bindमौजूद नहीं है, और यदि आप JAXB का उपयोग करना चाहते हैं, जिसमें सम्‍मिलित है, तो आपको मावेन से JAXB API और JAXB रनटाइमDatatypeConverter इंस्टॉल करना होगा ।

उदाहरण उपयोग:

byte bytes[] = {(byte)0, (byte)0, (byte)134, (byte)0, (byte)61};
String hex = javax.xml.bind.DatatypeConverter.printHexBinary(bytes);

में परिणाम होगा:

000086003D

यह इस एक के रूप में एक ही जवाब ।


13
एक अच्छा समाधान, हालांकि दुख की बात है कि एंड्रॉइड में मान्य नहीं है।
काज़्रीको

@Kazriko शायद आप code.google.com/p/dalvik/wiki/JavaxPackages पढ़ना चाहते हैं । यह Android में javax classes प्राप्त करने का एक तरीका है। लेकिन अगर आप केवल हेक्स में कनवर्ट करना चाहते हैं, तो यह परेशानी के लायक नहीं है।
फोनिक्स


3
@PhoneixS यह अभी भी है, लेकिन डिफ़ॉल्ट रनटाइम (जावा 9 मॉड्यूल के कारण) का हिस्सा नहीं है।
स्पॉटलाइट

2
javax.xml.bind पर भरोसा न करें, यह ठीक संकलन करता है लेकिन रनटाइम पर नहीं पाया जा सकता है। यदि आप करते हैं, तो java.lang.NoClassDefFoundError को संभालने के लिए तैयार रहें
दिमित्री

227

सबसे सरल समाधान, कोई बाहरी लिबास, कोई अंक स्थिरांक:

public static String byteArrayToHex(byte[] a) {
   StringBuilder sb = new StringBuilder(a.length * 2);
   for(byte b: a)
      sb.append(String.format("%02x", b));
   return sb.toString();
}

14
यह बहुत धीमी है, शीर्ष प्रतिक्रिया में एक की तुलना में औसतन 1000 गुना धीमी (162 बाइट्स लंबी)। यदि प्रदर्शन मायने रखता है, तो String.Format का उपयोग करने से बचें।
pt123

8
शायद धीमा। यह कभी-कभार होने वाली चीजों के लिए अच्छा है, जैसे कि लॉगिन या समान।
सूचक नल

29
अगर यह धीमा है, तो क्या? मेरे उपयोग के मामले में यह सिर्फ डिबग स्टेटमेंट के लिए है, इसलिए इस कोड के टुकड़े के लिए धन्यवाद।
वाइकिंगस्टीवेट

8
कई दर्जनों kB की एक अतिरिक्त JAR फ़ाइलों को शामिल करके एक पुस्तकालय का पुन: उपयोग करना बिलकुल भी कारगर नहीं होगा यदि आपको इसकी आवश्यकता है तो यह फ़ंक्शन (एंड्रॉइड जैसे कुछ प्लेटफार्मों पर, संपूर्ण जार अंतिम अनुप्रयोग में शामिल हो जाता है)। और कभी-कभी कम और अधिक स्पष्ट कोड बेहतर होता है जब प्रदर्शन की आवश्यकता नहीं होती है।
personne3000

2
@ personne3000 हो सकता है, लेकिन उस मामले में आपको स्ट्रीम समर्थन की आवश्यकता है, न कि एक कॉल सुविधा की। यह समझना और याद रखना आसान है, और इसलिए इसे बनाए रखना आसान है।
मार्टन बोदवेस

59

पूर्णता के लिए एक अमरूद का घोल:

import com.google.common.io.BaseEncoding;
...
byte[] bytes = "Hello world".getBytes(StandardCharsets.UTF_8);
final String hex = BaseEncoding.base16().lowerCase().encode(bytes);

अब hexहै "48656c6c6f20776f726c64"


अमरूद में भी आप इस्तेमाल कर सकते हैं new HashCode(bytes).toString()
mfulton26

1
अमरूद 22.0 के रूप में यह हैHashCode.fromBytes(checksum).toString()
Devstr

43

यह सरल ऑनलाइनर मेरे लिए
String result = new BigInteger(1, inputBytes).toString(16);
EDIT काम करता है - इसके उपयोग से अग्रणी शून्य को हटा दिया जाएगा, लेकिन हे ने मेरे उपयोग-मामले के लिए काम किया। @Voicu को इंगित करने के लिए धन्यवाद


56
यह ऑन्लाइनर अग्रणी शून्य बाइट्स को गिराता है
वोइकु

@Voicu ... और यह समय के अग्रणी शून्य 50% को जोड़ देगा।
मार्टन बॉडीवेज़

27

यहां सरल (वन-लाइनर) से लेकर कॉम्प्लेक्स (विशाल पुस्तकालय) तक के कुछ सामान्य विकल्प दिए गए हैं। यदि आप प्रदर्शन में रुचि रखते हैं, तो नीचे दिए गए माइक्रो बेंचमार्क देखें।

विकल्प 1: कोड स्निपेट - सरल

एक बहुत ही सरल उपाय है BigIntegerहेक्स प्रतिनिधित्व का उपयोग करना :

new BigInteger(1, someByteArray).toString(16)

ध्यान दें कि चूंकि यह संख्या बाइट-स्ट्रिंग्स को मनमाने ढंग से नहीं संभालती है, यह अग्रणी शून्य को छोड़ देगा - यह वह हो सकता है या नहीं जो आप चाहते हैं (जैसे कि 3 बाइट इनपुट के लिए 000AE3बनाम 0AE3)। यह भी बहुत धीमा है, अगले विकल्प की तुलना में लगभग 100x धीमा

विकल्प 2: कोड स्निपेट - उन्नत

यहाँ एक पूर्ण विशेषताओं, कॉपी और पेस्ट करने योग्य कोड स्निपेट है जो ऊपरी / लोअरकेस और एंडियननेस का समर्थन करता है । यह मेमोरी जटिलता को कम करने और प्रदर्शन को अधिकतम करने के लिए अनुकूलित है और सभी आधुनिक जावा संस्करणों (5+) के साथ संगत होना चाहिए।

private static final char[] LOOKUP_TABLE_LOWER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
private static final char[] LOOKUP_TABLE_UPPER = new char[]{0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46};

public static String encode(byte[] byteArray, boolean upperCase, ByteOrder byteOrder) {

    // our output size will be exactly 2x byte-array length
    final char[] buffer = new char[byteArray.length * 2];

    // choose lower or uppercase lookup table
    final char[] lookup = upperCase ? LOOKUP_TABLE_UPPER : LOOKUP_TABLE_LOWER;

    int index;
    for (int i = 0; i < byteArray.length; i++) {
        // for little endian we count from last to first
        index = (byteOrder == ByteOrder.BIG_ENDIAN) ? i : byteArray.length - i - 1;

        // extract the upper 4 bit and look up char (0-A)
        buffer[i << 1] = lookup[(byteArray[index] >> 4) & 0xF];
        // extract the lower 4 bit and look up char (0-A)
        buffer[(i << 1) + 1] = lookup[(byteArray[index] & 0xF)];
    }
    return new String(buffer);
}

public static String encode(byte[] byteArray) {
    return encode(byteArray, false, ByteOrder.BIG_ENDIAN);
}

Apache v2 लाइसेंस और डिकोडर के साथ पूर्ण स्रोत कोड यहां पाया जा सकता है

विकल्प 3: एक छोटे से अनुकूलित पुस्तकालय का उपयोग करना: बाइट्स-जावा

अपने पिछले प्रोजेक्ट पर काम करते हुए, मैंने जावा में बाइट्स के साथ काम करने के लिए यह छोटा टूलकिट बनाया। इसकी कोई बाहरी निर्भरता नहीं है और यह जावा 7+ के साथ संगत है। यह दूसरों के बीच में शामिल है, एक बहुत तेज और अच्छी तरह से परीक्षण किया गया हेक्स एन / डिकोडर:

import at.favre.lib.bytes.Bytes;
...
Bytes.wrap(someByteArray).encodeHex()

आप इसे जीथब: बाइट्स-जावा पर देख सकते हैं

विकल्प 4: अपाचे कॉमन्स कोडेक

बेशक वहाँ अच्छा 'राजभाषा कॉमन्स कोडेक्स है । ( आगे की राय को चेतावनी देते हुए ) ऊपर उल्लिखित परियोजना पर काम करते समय मैंने कोड का विश्लेषण किया और काफी निराश हुआ; बहुत सारे डुप्लिकेट असंगठित कोड, अप्रचलित और विदेशी कोडेक्स शायद केवल बहुत कम और काफी अधिक इंजीनियर और लोकप्रिय कोडेक्स (विशेष रूप से बेस 64) के धीमे कार्यान्वयन के लिए उपयोगी हैं। इसलिए यदि आप इसका उपयोग करना चाहते हैं या एक विकल्प चाहते हैं तो मैं एक सूचित निर्णय लूंगा। वैसे भी, यदि आप अभी भी इसका उपयोग करना चाहते हैं, तो यहां एक कोड स्निपेट है:

import org.apache.commons.codec.binary.Hex;
...
Hex.encodeHexString(someByteArray));

विकल्प 5: Google अमरूद

अधिक बार आप पहले से ही एक निर्भरता के रूप में अमरूद नहीं है । यदि ऐसा है तो बस उपयोग करें:

import com.google.common.io.BaseEncoding;
...
BaseEncoding.base16().lowerCase().encode(someByteArray);

विकल्प 6: वसंत सुरक्षा

यदि आप स्प्रिंग सुरक्षा के साथ स्प्रिंग फ्रेमवर्क का उपयोग करते हैं तो आप निम्नलिखित का उपयोग कर सकते हैं:

import org.springframework.security.crypto.codec.Hex
...
new String(Hex.encode(someByteArray));

विकल्प 7: उछालभरी महल

यदि आप पहले से ही सुरक्षा ढांचे का उपयोग करते हैं तो उछालभरी कैसल आप इसके उपयोग का उपयोग कर सकते हैं Hex:

import org.bouncycastle.util.encoders.Hex;
...
Hex.toHexString(someByteArray);

नहीं वास्तव में विकल्प 8: जावा 9+ संगतता या 'JAXBs javax / xml / bind / DatatypeConverter का उपयोग न करें'

पिछले जावा (8 और नीचे) संस्करणों में JAXB के लिए जावा कोड रनटाइम निर्भरता के रूप में शामिल किया गया था। जावा 9 और आरा मॉड्यूलाइज़ेशन के बाद से आपका कोड स्पष्ट घोषणा के बिना इसके मॉड्यूल के बाहर अन्य कोड तक नहीं पहुंच सकता है। इसलिए अगर आपको कोई अपवाद मिलता है, तो जागरूक रहें:

java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException

जावा 9+ के साथ एक जेवीएम पर चलने पर। यदि हां, तो कार्यान्वयन को ऊपर दिए गए किसी भी विकल्प पर स्विच करें। यह प्रश्न भी देखें ।


माइक्रो बेंचमार्क

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

| Name (ops/s)         |    16 byte |    32 byte |  128 byte | 0.95 MB |
|----------------------|-----------:|-----------:|----------:|--------:|
| Opt1: BigInteger     |  2,088,514 |  1,008,357 |   133,665 |       4 |
| Opt2/3: Bytes Lib    | 20,423,170 | 16,049,841 | 6,685,522 |     825 |
| Opt4: Apache Commons | 17,503,857 | 12,382,018 | 4,319,898 |     529 |
| Opt5: Guava          | 10,177,925 |  6,937,833 | 2,094,658 |     257 |
| Opt6: Spring         | 18,704,986 | 13,643,374 | 4,904,805 |     601 |
| Opt7: BC             |  7,501,666 |  3,674,422 | 1,077,236 |     152 |
| Opt8: JAX-B          | 13,497,736 |  8,312,834 | 2,590,940 |     346 |

स्पेक्स: JDK 8u202, i7-7700K, Win10, 24GB Ram। यहां पूरा मानदंड देखें ।




17

मुझे यहां तीन अलग-अलग तरीके मिले: http://www.rgagnon.com/javadetails/java-0596.html

सबसे सुंदर एक, जैसा कि वह भी नोट करता है, मुझे लगता है कि यह एक है:

static final String HEXES = "0123456789ABCDEF";
public static String getHex( byte [] raw ) {
    if ( raw == null ) {
        return null;
    }
    final StringBuilder hex = new StringBuilder( 2 * raw.length );
    for ( final byte b : raw ) {
        hex.append(HEXES.charAt((b & 0xF0) >> 4))
            .append(HEXES.charAt((b & 0x0F)));
    }
    return hex.toString();
}

अन्य तरीके 5ms में मेरे 64 बाइट के नमूने पर चल रहे थे, यह 0ms में चलता है। प्रारूप जैसे किसी अन्य स्ट्रिंग फ़ंक्शन की कमी के लिए संभवतः सबसे अच्छा है।
जोसेफ वासना

if (raw == null) return nullतेजी से विफल नहीं है। आप कभी nullकुंजी का उपयोग क्यों करेंगे ?
Maarten Bodewes

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

16

लुकअप टेबल को संग्रहीत करने की मामूली लागत पर यह कार्यान्वयन सरल और बहुत तेज़ है।

 private static final char[] BYTE2HEX=(
    "000102030405060708090A0B0C0D0E0F"+
    "101112131415161718191A1B1C1D1E1F"+
    "202122232425262728292A2B2C2D2E2F"+
    "303132333435363738393A3B3C3D3E3F"+
    "404142434445464748494A4B4C4D4E4F"+
    "505152535455565758595A5B5C5D5E5F"+
    "606162636465666768696A6B6C6D6E6F"+
    "707172737475767778797A7B7C7D7E7F"+
    "808182838485868788898A8B8C8D8E8F"+
    "909192939495969798999A9B9C9D9E9F"+
    "A0A1A2A3A4A5A6A7A8A9AAABACADAEAF"+
    "B0B1B2B3B4B5B6B7B8B9BABBBCBDBEBF"+
    "C0C1C2C3C4C5C6C7C8C9CACBCCCDCECF"+
    "D0D1D2D3D4D5D6D7D8D9DADBDCDDDEDF"+
    "E0E1E2E3E4E5E6E7E8E9EAEBECEDEEEF"+
    "F0F1F2F3F4F5F6F7F8F9FAFBFCFDFEFF").toCharArray();
   ; 

  public static String getHexString(byte[] bytes) {
    final int len=bytes.length;
    final char[] chars=new char[len<<1];
    int hexIndex;
    int idx=0;
    int ofs=0;
    while (ofs<len) {
      hexIndex=(bytes[ofs++] & 0xFF)<<1;
      chars[idx++]=BYTE2HEX[hexIndex++];
      chars[idx++]=BYTE2HEX[hexIndex];
    }
    return new String(chars);
  }

6
BYTE2HEXएक सरल forचक्र के साथ सरणी को इनिशियलाइज़ क्यों नहीं किया जाता है?
icza

@icza क्या स्थैतिक अंतिम (उर्फ स्थिर) क्षेत्र के साथ भी संभव है?
नेवलिस

1
@nevelis इसे एक static { }ब्लॉक में सौंपा जा सकता है ।
だ ち ゃ ん よ

1
@icza क्योंकि इसे बनाने की तुलना में लुकअप टेबल को हार्डकोड करना तेज़ है। यहाँ मेमोरी कॉम्प्लेक्सिटी को टाइम कॉम्प्लेक्सिटी के साथ कारोबार किया जाता है। अधिक स्मृति की आवश्यकता है, लेकिन तेज़ (दोनों छोरों पर थोड़ा सा)
पैट्रिक फेवर

8

इस बारे में कैसा है?

    String byteToHex(final byte[] hash)
    {
        Formatter formatter = new Formatter();
        for (byte b : hash)
        {
            formatter.format("%02x", b);
        }
        String result = formatter.toString();
        formatter.close();
        return result;
    }

3

हमें किसी बाहरी पुस्तकालय का उपयोग करने या लूप और स्थिरांक के आधार पर कोड लिखने की आवश्यकता नहीं है।
बस इतना काफी है:

byte[] theValue = .....
String hexaString = new BigInteger(1, theValue).toString(16);

1
यह वह जगह है बहुत everconfusedGuy के उत्तर के समान है।
20

2

मैं इसका उपयोग करना पसंद करता हूं:

final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes, int offset, int count) {
    char[] hexChars = new char[count * 2];
    for ( int j = 0; j < count; j++ ) {
        int v = bytes[j+offset] & 0xFF;
        hexChars[j * 2] = hexArray[v >>> 4];
        hexChars[j * 2 + 1] = hexArray[v & 0x0F];
    }
    return new String(hexChars);
}

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


मूल प्रश्न बाइट [] स्ट्रिंग के लिए था। हेक्स को बाइट्स में देखें] या एक अलग सवाल पूछें, @ नोन्जेंट।
बमाको

2

मैं आमतौर पर डेब्यू स्टेटमेंट के लिए निम्न विधि का उपयोग करता हूं, लेकिन मुझे नहीं पता कि यह करने का सबसे अच्छा तरीका है या नहीं

private static String digits = "0123456789abcdef";

public static String toHex(byte[] data){
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i != data.length; i++)
    {
        int v = data[i] & 0xff;
        buf.append(digits.charAt(v >> 4));
        buf.append(digits.charAt(v & 0xf));
    }
    return buf.toString();
}

2
यदि आपके डेब्यूफ़र का दिन खराब है, तो समर्थन करने के लिए कई वर्णों के साथ स्ट्रिंगब्यूलर इंस्टेंटेशन में क्लीजिंग का प्रयास करें StringBuilder buf = new StringBuilder(data.length * 2);:।
ग्रेबियर

2

ठीक है, ऐसा करने के तरीकों का एक समूह है, लेकिन यदि आप एक पुस्तकालय का उपयोग करने का निर्णय लेते हैं, तो मैं आपकी परियोजना के बारे में बताने का सुझाव दूंगा कि यह देखने के लिए कि क्या एक पुस्तकालय में कुछ लागू किया गया है जो एक नई लाइब्रेरी जोड़ने से पहले ही आपकी परियोजना का हिस्सा है बस ऐसा करने के लिए। उदाहरण के लिए यदि आपके पास पहले से नहीं है

org.apache.commons.codec.binary.Hex

शायद आपके पास है ...

org.apache.xerces.impl.dv.util.HexBin


2

यदि आप स्प्रिंग सुरक्षा ढांचे का उपयोग कर रहे हैं, तो आप उपयोग कर सकते हैं:

import org.springframework.security.crypto.codec.Hex

final String testString = "Test String";
final byte[] byteArray = testString.getBytes();
System.out.println(Hex.encode(byteArray));

2

साधारण फ़ंक्शन के लिए उपयोगिता जार जोड़ना अच्छा विकल्प नहीं है। इसके बजाय अपने स्वयं के उपयोगिता वर्गों को इकट्ठा करें। निम्नलिखित तेजी से कार्यान्वयन संभव है।

public class ByteHex {

    public static int hexToByte(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 String[] byteToHexTable = new String[]
    {
        "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0A", "0B", "0C", "0D", "0E", "0F",
        "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1A", "1B", "1C", "1D", "1E", "1F",
        "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2A", "2B", "2C", "2D", "2E", "2F",
        "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3A", "3B", "3C", "3D", "3E", "3F",
        "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4A", "4B", "4C", "4D", "4E", "4F",
        "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5A", "5B", "5C", "5D", "5E", "5F",
        "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6A", "6B", "6C", "6D", "6E", "6F",
        "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7A", "7B", "7C", "7D", "7E", "7F",
        "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8A", "8B", "8C", "8D", "8E", "8F",
        "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9A", "9B", "9C", "9D", "9E", "9F",
        "A0", "A1", "A2", "A3", "A4", "A5", "A6", "A7", "A8", "A9", "AA", "AB", "AC", "AD", "AE", "AF",
        "B0", "B1", "B2", "B3", "B4", "B5", "B6", "B7", "B8", "B9", "BA", "BB", "BC", "BD", "BE", "BF",
        "C0", "C1", "C2", "C3", "C4", "C5", "C6", "C7", "C8", "C9", "CA", "CB", "CC", "CD", "CE", "CF",
        "D0", "D1", "D2", "D3", "D4", "D5", "D6", "D7", "D8", "D9", "DA", "DB", "DC", "DD", "DE", "DF",
        "E0", "E1", "E2", "E3", "E4", "E5", "E6", "E7", "E8", "E9", "EA", "EB", "EC", "ED", "EE", "EF",
        "F0", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "FA", "FB", "FC", "FD", "FE", "FF"
    };

    private static final String[] byteToHexTableLowerCase = new String[]
    {
        "00", "01", "02", "03", "04", "05", "06", "07", "08", "09", "0a", "0b", "0c", "0d", "0e", "0f",
        "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "1a", "1b", "1c", "1d", "1e", "1f",
        "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "2a", "2b", "2c", "2d", "2e", "2f",
        "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "3a", "3b", "3c", "3d", "3e", "3f",
        "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", "4a", "4b", "4c", "4d", "4e", "4f",
        "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", "5a", "5b", "5c", "5d", "5e", "5f",
        "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", "6a", "6b", "6c", "6d", "6e", "6f",
        "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", "7a", "7b", "7c", "7d", "7e", "7f",
        "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", "8a", "8b", "8c", "8d", "8e", "8f",
        "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", "9a", "9b", "9c", "9d", "9e", "9f",
        "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "aa", "ab", "ac", "ad", "ae", "af",
        "b0", "b1", "b2", "b3", "b4", "b5", "b6", "b7", "b8", "b9", "ba", "bb", "bc", "bd", "be", "bf",
        "c0", "c1", "c2", "c3", "c4", "c5", "c6", "c7", "c8", "c9", "ca", "cb", "cc", "cd", "ce", "cf",
        "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "da", "db", "dc", "dd", "de", "df",
        "e0", "e1", "e2", "e3", "e4", "e5", "e6", "e7", "e8", "e9", "ea", "eb", "ec", "ed", "ee", "ef",
        "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "fa", "fb", "fc", "fd", "fe", "ff"
    };

    public static String byteToHex(byte b){
        return byteToHexTable[b & 0xFF];
    }

    public static String byteToHex(byte[] bytes){
        if(bytes == null) return null;
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(byte b : bytes) sb.append(byteToHexTable[b & 0xFF]);
        return sb.toString();
    }

    public static String byteToHex(short[] bytes){
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(short b : bytes) sb.append(byteToHexTable[((byte)b) & 0xFF]);
        return sb.toString();
    }

    public static String byteToHexLowerCase(byte[] bytes){
        StringBuilder sb = new StringBuilder(bytes.length*2);
        for(byte b : bytes) sb.append(byteToHexTableLowerCase[b & 0xFF]);
        return sb.toString();
    }

    public static byte[] hexToByte(String hexString) {
        if(hexString == null) return null;
        byte[] byteArray = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            byteArray[i / 2] = (byte) (hexToByte(hexString.charAt(i)) * 16 + hexToByte(hexString.charAt(i+1)));
        }
        return byteArray;
    }

    public static byte hexPairToByte(char ch1, char ch2) {
        return (byte) (hexToByte(ch1) * 16 + hexToByte(ch2));
    }


}

1

@Maybewecouldstealavan द्वारा प्रस्तावित समाधान का एक छोटा संस्करण, जो आपको आउटपुट हेक्स स्ट्रिंग में एक साथ नेत्रहीन बंडल बाइट करने देता है:

 final static char[] HEX_ARRAY = "0123456789ABCDEF".toCharArray();
 final static char BUNDLE_SEP = ' ';

public static String bytesToHexString(byte[] bytes, int bundleSize /*[bytes]*/]) {
        char[] hexChars = new char[(bytes.length * 2) + (bytes.length / bundleSize)];
        for (int j = 0, k = 1; j < bytes.length; j++, k++) {
                int v = bytes[j] & 0xFF;
                int start = (j * 2) + j/bundleSize;

                hexChars[start] = HEX_ARRAY[v >>> 4];
                hexChars[start + 1] = HEX_ARRAY[v & 0x0F];

                if ((k % bundleSize) == 0) {
                        hexChars[start + 2] = BUNDLE_SEP;
                }   
        }   
        return new String(hexChars).trim();    
}

अर्थात्:

bytesToHexString("..DOOM..".toCharArray().getBytes(), 2);
2E2E 444F 4F4D 2E2E

bytesToHexString("..DOOM..".toCharArray().getBytes(), 4);
2E2E444F 4F4D2E2E

1

इस पृष्ठ पर ऐसा कोई समाधान नहीं खोज सकते जो नहीं करता हो

  1. एक लूप का उपयोग करें
  2. Javax.xml.bind.DatatypeConverter का उपयोग करें जो ठीक संकलन करता है लेकिन अक्सर रनवे पर java.lang.NoClassDefFoundError फेंकता है।

यहां एक समाधान है जिसमें ऊपर की खामियां नहीं हैं (कोई वादा नहीं है, हालांकि मेरे पास अन्य दोष नहीं हैं)

import java.math.BigInteger;

import static java.lang.System.out;
public final class App2 {
    // | proposed solution.
    public static String encode(byte[] bytes) {          
        final int length = bytes.length;

        // | BigInteger constructor throws if it is given an empty array.
        if (length == 0) {
            return "00";
        }

        final int evenLength = (int)(2 * Math.ceil(length / 2.0));
        final String format = "%0" + evenLength + "x";         
        final String result = String.format (format, new BigInteger(bytes));

        return result;
    }

    public static void main(String[] args) throws Exception {
        // 00
        out.println(encode(new byte[] {})); 

        // 01
        out.println(encode(new byte[] {1})); 

        //203040
        out.println(encode(new byte[] {0x20, 0x30, 0x40})); 

        // 416c6c20796f75722062617365206172652062656c6f6e6720746f2075732e
        out.println(encode("All your base are belong to us.".getBytes()));
    }
}   

मैं इसे 62 opcodes के तहत नहीं प्राप्त कर सका, लेकिन यदि आप 0 ब्रेड के बिना रह सकते हैं यदि पहली बाइट 0x10 से कम है, तो निम्न समाधान केवल 23 opcodes का उपयोग करता है। वास्तव में दिखाता है कि "खुद को लागू करना कितना आसान है" जैसे "पैड के साथ पैड एक शून्य अगर स्ट्रिंग की लंबाई विषम है" तो बहुत महंगा हो सकता है अगर एक देशी कार्यान्वयन पहले से ही उपलब्ध नहीं है (या इस मामले में, अगर BigInteger में शून्य के साथ उपसर्ग करने का विकल्प था तार)।

public static String encode(byte[] bytes) {          
    final int length = bytes.length;

    // | BigInteger constructor throws if it is given an empty array.
    if (length == 0) {
        return "00";
    }

    return new BigInteger(bytes).toString(16);
}

1

मेरा समाधान शायद WeWeCouldStealAVan के समाधान पर आधारित है, लेकिन किसी भी अतिरिक्त आवंटित लुकअप तालिकाओं पर निर्भर नहीं करता है। यह किसी भी 'इंट-टू-चार' कास्ट हैक्स का उपयोग नहीं करता है (वास्तव में, Character.forDigit()यह करता है, यह जांचने के लिए कुछ तुलना करता है कि अंक वास्तव में क्या है) और इस तरह थोड़ा धीमा हो सकता है। आप जहां चाहें इसका उपयोग करने के लिए स्वतंत्र महसूस करें। चीयर्स।

public static String bytesToHex(final byte[] bytes)
{
    final int numBytes = bytes.length;
    final char[] container = new char[numBytes * 2];

    for (int i = 0; i < numBytes; i++)
    {
        final int b = bytes[i] & 0xFF;

        container[i * 2] = Character.forDigit(b >>> 4, 0x10);
        container[i * 2 + 1] = Character.forDigit(b & 0xF, 0x10);
    }

    return new String(container);
}

0

// शिफ्ट बाइट्स अधिक कुशल है // आप इसे भी उपयोग कर सकते हैं

public static String getHexString (String s) 
{
    byte[] buf = s.getBytes();

    StringBuffer sb = new StringBuffer();

    for (byte b:buf)
    {
        sb.append(String.format("%x", b));
    }


        return sb.toString();
}

0

यदि आप अजगर के लिए बाइट सरणी की तरह देख रहे हैं, तो मैंने इस जावा कार्यान्वयन को अजगर में बदल दिया है।

class ByteArray:

@classmethod
def char(cls, args=[]):
    cls.hexArray = "0123456789ABCDEF".encode('utf-16')
    j = 0
    length = (cls.hexArray)

    if j < length:
        v = j & 0xFF
        hexChars = [None, None]
        hexChars[j * 2] = str( cls.hexArray) + str(v)
        hexChars[j * 2 + 1] = str(cls.hexArray) + str(v) + str(0x0F)
        # Use if you want...
        #hexChars.pop()

    return str(hexChars)

array = ByteArray()
print array.char(args=[])

0
  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;
  } 

0

यहां एक समान java.util.Base64कार्यान्वयन (आंशिक) है, क्या यह सुंदर नहीं है?

public class Base16/*a.k.a. Hex*/ {
    public static class Encoder{
        private static char[] toLowerHex={'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
        private static char[] toUpperHex={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        private boolean upper;
        public Encoder(boolean upper) {
            this.upper=upper;
        }
        public String encode(byte[] data){
            char[] value=new char[data.length*2];
            char[] toHex=upper?toUpperHex:toLowerHex;
            for(int i=0,j=0;i<data.length;i++){
                int octet=data[i]&0xFF;
                value[j++]=toHex[octet>>4];
                value[j++]=toHex[octet&0xF];
            }
            return new String(value);
        }
        static final Encoder LOWER=new Encoder(false);
        static final Encoder UPPER=new Encoder(true);
    }
    public static Encoder getEncoder(){
        return Encoder.LOWER;
    }
    public static Encoder getUpperEncoder(){
        return Encoder.UPPER;
    }
    //...
}

0
private static String bytesToHexString(byte[] bytes, int length) {
        if (bytes == null || length == 0) return null;

        StringBuilder ret = new StringBuilder(2*length);

        for (int i = 0 ; i < length ; i++) {
            int b;

            b = 0x0f & (bytes[i] >> 4);
            ret.append("0123456789abcdef".charAt(b));

            b = 0x0f & bytes[i];
            ret.append("0123456789abcdef".charAt(b));
        }

        return ret.toString();
    }

0
Converts bytes data to hex characters

@param bytes byte array to be converted to hex string
@return byte String in hex format

private static String bytesToHex(byte[] bytes) {
    char[] hexChars = new char[bytes.length * 2];
    int v;
    for (int j = 0; j < bytes.length; j++) {
        v = bytes[j] & 0xFF;
        hexChars[j * 2] = HEX_ARRAY[v >>> 4];
        hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
    }
    return new String(hexChars);
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.