জাভা ব্যবহার করে একটি হেক্স ডাম্পের একটি স্ট্রিং প্রতিনিধিত্বকে বাইট অ্যারেতে রূপান্তর করবেন?


372

আমি একটি দীর্ঘ স্ট্রিং (ডাম্প থেকে) রূপান্তর করার জন্য একটি উপায় খুঁজছি যা হেক্স মানকে বাইট অ্যারেতে উপস্থাপন করে।

আমি এখানে একই প্রশ্নটি পোস্টকারী ব্যক্তির চেয়ে এর চেয়ে ভাল বলতে পারি না ।

তবে এটি আসল রাখতে, আমি এটিকে আমার নিজের "00A0BF"মত করে বলব : ধরুন আমার কাছে একটি স্ট্রিং রয়েছে যা আমি হিসাবে ব্যাখ্যা করতে চাই

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

আমার কি করা উচিৎ?

আমি জাভা নবাগত এবং BigIntegerশীর্ষস্থানীয় হেক্স জেরো ব্যবহার করে এবং পর্যবেক্ষণ শেষ করেছি । তবে আমি মনে করি এটি কুরুচিপূর্ণ এবং আমি নিশ্চিত যে আমি কিছু সাধারণ অনুপস্থিত।



আমি 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" এর জন্য কাজ করে না। এটি একটি
জাভা.এল.এল স্ট্রিংইন্ডেক্স আউট অফফাউন্ডসএক্সপেশন

49
"0" বৈধ ইনপুট নয়। বাইটগুলির জন্য প্রতিটি জন্য দুটি হেক্সিডিসিমাল ডিজিট প্রয়োজন। উত্তরের হিসাবে নোট হিসাবে, "আর্গুমেন্ট চেক যোগ করতে নির্দ্বিধায় ... যদি তর্কটি নিরাপদ হিসাবে পরিচিত না হয়।"
ডেভ এল

12
javax.xML.bind.DatatypeConverter.parseHexBinary (হেক্স স্ট্রিং) আমার মাইক্রো পরীক্ষাগুলিতে উপরের সমাধানের তুলনায় প্রায় 20% দ্রুত বলে মনে হচ্ছে (যার জন্য এটি সামান্যই মূল্যবান), পাশাপাশি সঠিকভাবে অবৈধ ইনপুটটিতে ব্যতিক্রম ছোঁড়া (যেমন "জিজি") কোনও বৈধ হেক্সস্ট্রিং নয় তবে প্রস্তাবিত হিসাবে সমাধানটি ব্যবহার করে -77 ফিরে আসবে)।
ট্রেভর ফ্রিম্যান

6
@ ডেডালাসআল্ফা এটি আপনার প্রসঙ্গে নির্ভর করে তবে সাধারণত আমি মনে করি যে এ জাতীয় জিনিসগুলির সাথে দ্রুত এবং জোরে ব্যর্থ হওয়া ভাল যা আপনি চুপটি করে ভুল ডেটা ফেরানোর পরিবর্তে নিজের অনুমানগুলি ঠিক করতে পারেন।
ডেভ এল

331

এক-liners,:

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 জিগসে এটি আর (ডিফল্ট) জাভা.সে রুট সেটের অংশ নয় তাই এটি ক্লাসনটফাউন্ডএক্সেপশন হয়ে যাবে যদি আপনি - ADD- মডিউলগুলি java.se.ee নির্দিষ্ট না করেন (@ ধন্যবাদ আপনাকে eckes)
  • অ্যান্ড্রয়েডে উপলব্ধ নয় (এটি Fabianলক্ষ করার জন্য ধন্যবাদ ) তবে আপনার সিস্টেমে কোনও কারণে অভাব বোধ করলে আপনি কেবল উত্স কোডটি নিতে পারেন javax.xmlBert Regelinkউত্স আহরণের জন্য @ কে ধন্যবাদ

14
IMHO এর স্বীকৃত / শীর্ষ উত্তর হওয়া উচিত কারণ এটি সংক্ষিপ্ত এবং পরিষ্কার (@ ড্যাভেলের উত্তরের বিপরীতে) এবং কোনও বাহ্যিক লিবসের প্রয়োজন নেই (যেমন স্ক্যাফম্যানের উত্তর)। এছাড়াও, <সাইকেলের পুনঃতদন্ত সম্পর্কে একটি জীর্ণ রসিকতা প্রবেশ করুন>
প্রিয়দু নিমরে

9
উদাহরণস্বরূপ ডেটাটাইপ কনভার্টর ক্লাস অ্যান্ড্রয়েডে উপলব্ধ নয়।
ফ্যাবিয়ান

4
সতর্কতা: জাভা 9 জিগসে এটি আর (ডিফল্ট) java.seরুট সেটের অংশ নয় তাই এটি ClassNotFoundExceptionনির্দিষ্ট না করলে এর ফলাফল আসবে--add-modules java.se.ee

2
@ লন্ডেবার্বা আমি মনে করি javax.xml.bind.DatatypeConverterইতিমধ্যে বেস 64 এর ডেটা এনকোডিং / ডিকোড করার জন্য একটি পদ্ধতি সরবরাহ করেছে। দেখুন parseBase64Binary()এবং printBase64Binary()
ড্র্যাগশট

2
সমস্যাগুলি যুক্ত করতে DataTypeConverter, জাভা এসই 11 পুরোপুরি জ্যাকএক্সবি এপিআই সরিয়ে ফেলেছে এবং এখন কেবল জাভা ইই সহ অন্তর্ভুক্ত রয়েছে। : আপনি একটা ম্যাভেন নির্ভরতা যেমন যুক্ত করতে পারেন এখানে প্রস্তাব stackoverflow.com/a/43574427/7347751
ডেভিড Mordigal

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 ()
ডেভ এল।

এটি আকর্ষণীয় ছিল। তবে আমি তাদের সমাধানগুলি মেনে চলা কঠিন বলে মনে করি। আপনি প্রস্তাবিত (এর চেয়ে বেশি সংখ্যার চরিত্র পরীক্ষা করা ব্যতীত) এর কোনও সুবিধা আছে কি?
রাফ্রাফ

38

আপনি এখন ব্যবহার করতে পারেন BaseEncoding মধ্যে guavaএই কাজ করা সম্ভব।

BaseEncoding.base16().decode(string);

বিপরীতে এটি ব্যবহার করুন

BaseEncoding.base16().encode(bytes);

27

আসলে, আমি মনে করি বিগইন্টিজার সমাধানটি খুব সুন্দর:

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

সম্পাদনা: পোস্টার দ্বারা উল্লিখিত হিসাবে জিরো নেতৃস্থানীয় জন্য নিরাপদ নয়


আমি প্রথম দিকে তাই ভেবেছি। এবং এটি নথিভুক্ত করার জন্য আপনাকে ধন্যবাদ - আমি কেবল ভাবছিলাম আমার উচিত ... এটি কিছু অদ্ভুত কাজ করেছে যা আমি সত্যই বুঝতে পারি নি - যেমন কিছু শীর্ষস্থানীয় 0x00 বাদ দেওয়া এবং 156 বাইট স্ট্রিং-এ 1 বাইটের ক্রমটি মিশ্রন করা সাথে খেলছিলাম।
রাফরাফ

2
শীর্ষস্থানীয় 0 এর সম্পর্কে এটি একটি ভাল বিষয়। আমি নিশ্চিত না যে আমি বিশ্বাস করি এটি বাইটের ক্রমটি মিশ্রিত করতে পারে এবং এটি প্রদর্শিত হতে আগ্রহী হবে।
ডেভ এল।

1
হ্যাঁ, আমি এটি বলার সাথে সাথেই, আমিও বিশ্বাস করি না :) আমি বিগআইন্টার থেকে বাইট অ্যারের সাথে এমমিয়ার্সফ্রমহেক্সস্ট্রিংয়ের সাথে এবং (আপত্তিজনক স্ট্রিংয়ের বিপরীতে 0x00 নেই) চালিয়েছি - তারা অভিন্ন ছিল। "মিক্স আপ" ঘটেছে, তবে এটি অন্যরকম কিছু হতে পারে। আমি আগামীকাল আরও নিবিড়ভাবে উইল্লুক করলাম
রাফ্রাফ

3
বিগইন্টিজারের সাথে সমস্যাটি হ'ল একটি "সাইন বিট" থাকতে হবে। যদি শীর্ষস্থানীয় বাইটে উচ্চ বিট সেট থাকে তবে ফলস্বরূপ বাইট অ্যারের 1 ম স্থানে অতিরিক্ত 0 থাকে has তবে এখনও +1।
ধূসর

25

এক-liners,:

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

আপনাদের মধ্যে যারা পিছনে আসল কোডে আগ্রহী জন্য এক-liners, থেকে FractalizeR (আমি প্রয়োজন যে যেহেতু javax.xml.bind অ্যান্ড্রয়েড (ডিফল্ট অনুসারে) জন্য উপলব্ধ নয়) এই থেকে আসে com.sun.xml.internal.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
ডেটাটাইপ কনভার্টর ডিফল্টভাবে জাভা 9 তেও উপলভ্য নয়। বিপজ্জনক বিষয়টি কোডটি ব্যবহার করে জাভা ১.৮ বা তার আগের (জাভা 9 পূর্বে উত্সের সেটিংস সহ) সংকলন করবে তবে জাভা 9 এর অধীনে "--add-Modules java.se.ee" ছাড়াই একটি রানটাইম ব্যতিক্রম পাবে।
স্টিফেন এম -on ধর্মঘট-

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
এটি কেবলমাত্র তখনই কাজ করে যদি ইনপুট স্ট্রিং (হেক্সস্ট্রিং) এর একাধিক অক্ষর থাকে। অন্যথায়: "মূল" জাভা.লাংয়ের থ্রেডে ব্যতিক্রম l বৈধতা অরগমেন্ট এক্সেপশন: হেক্সবাইনারিটির সম-দৈর্ঘ্য হওয়া দরকার:
ওভ্ডসরন

3
ওহ, এটি নির্দেশ করার জন্য ধন্যবাদ। কোনও ব্যবহারকারীর কাছে সত্যই একটি বিজোড় সংখ্যক অক্ষর থাকা উচিত নয় কারণ বাইট অ্যারেটি {0x00,0xA0,0xBf as হিসাবে উপস্থাপন করা হয়} প্রতিটি বাইটে দুটি হেক্স ডিজিট বা নিবল থাকে। সুতরাং যে কোনও সংখ্যক বাইটের সর্বদা একটি সমান সংখ্যক অক্ষর থাকা উচিত। এটি উল্লেখ করার জন্য ধন্যবাদ।
গ্রেকইঞ্জাইনার

8
আপনি java.xML.bind.DatatypeConverter.parseHexBinary (hexString) সরাসরি HexBinaryAdapter ব্যবহার করার পরিবর্তে (যা পরিবর্তে ডেটাটাইপকোনভার্টার কল করে) ব্যবহার করতে পারেন। এইভাবে আপনাকে কোনও অ্যাডাপ্টর ইনস্ট্যান্স অবজেক্ট তৈরি করতে হবে না (যেহেতু ডেটাটাইপ কনভার্টার পদ্ধতিগুলি স্থিতিশীল)।
ট্রেভর ফ্রিম্যান

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

কেবলমাত্র সম্ভাব্য ইস্যুটি আমি দেখতে পাচ্ছি যদি ইনপুট স্ট্রিংটি অত্যন্ত দীর্ঘ হয়; চ্যারিআররে কল করা () স্ট্রিংয়ের অভ্যন্তরীণ অ্যারের একটি অনুলিপি তৈরি করে।

সম্পাদনা: ওহ, এবং যাইহোক, জাভাতে বাইটস স্বাক্ষরিত হয়েছে, সুতরাং আপনার ইনপুট স্ট্রিং [0, 160, 191] এর পরিবর্তে [0, -96, -65] এ রূপান্তরিত হয়। তবে আপনি সম্ভবত এটি ইতিমধ্যে জানতেন।


1
ধন্যবাদ মাইকেল - আপনি জীবন রক্ষাকারী! একটি ব্ল্যাকবেরি প্রকল্পে কাজ করা এবং একটি বাইটের একটি স্ট্রিং প্রতিনিধিত্বকে আবার বাইটে রূপান্তরিত করার চেষ্টা করা হচ্ছে ... আরআইএম এর "বাইট.পারসবিট (বাইটস্ট্রিং, 16)" পদ্ধতি ব্যবহার করে। একটি নম্বর ফরম্যাটএক্সসিপশন নিক্ষেপ করা হয়েছে। কী কারণে তা নির্ধারণ করতে কয়েক ঘন্টা সময় কাটালেন। আপনার "Integer.praseInt ()" এর পরামর্শটি কৌশলটি কার্যকর করেছে। আবার ধন্যবাদ!!
বোনানজাড্রাইভার

12

অ্যান্ড্রয়েডে, আপনি যদি হেক্সের সাথে কাজ করছেন তবে আপনি ওকিও চেষ্টা করতে পারেন ।

সাধারণ ব্যবহার:

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

এবং ফলাফল হবে

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

আমি বিভিন্ন বিভিন্ন পদ্ধতি পরীক্ষা করেছি তবে এটি একটি কমপক্ষে দ্বিগুণ দ্রুত!
পবি

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 বাইট.পার্সবিাইট এসডিকে ডকুমেন্টেশনে বিজ্ঞাপন হিসাবে কাজ করছে না

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
@ এমমিয়ার্স: হুআ। এটা ভালো না. বিভ্রান্তির জন্য দুঃখিত। @ রবিগাদ: 9 সি তে একই সমস্যা রয়েছে কারণ এই ক্ষেত্রে উচ্চ বিট সেট করা আছে।
ব্লেয়ার কনরাড

(বাইট) শর্ট. পার্সশোর্ট (এটি বাইট, 16) সেই সমস্যাটি সমাধান করে
জামে হিক্স

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

এই পদ্ধতিটি স্পেসে বিভক্ত হেক্স মানগুলিকে বিভক্ত করে তবে এটিকে অন্য কোনও মানদণ্ডে যেমন দুটি অক্ষরের গোষ্ঠীতে বিভক্ত করা শক্ত হবে না।


স্ট্রিং কনটেনটেশন অপ্রয়োজনীয়। কেবল পূর্ণসংখ্যা.ভালিউওফ (ভ্যাল, 16) ব্যবহার করুন।
মাইকেল ম্যাইইয়ার্স

আমি এর আগে রেডিক্স রূপান্তরগুলি ব্যবহার করার চেষ্টা করেছি এবং আমার মিশ্র ফলাফল
পেয়েছে

ধন্যবাদ - অদ্ভুতভাবে এটি এই স্ট্রিংয়ের সাথে সূক্ষ্মভাবে কাজ করে: "9C001C" বা "001C21" এবং এটির সাথে ব্যর্থ হয়: "9C001C21" থ্রেডে ব্যতিক্রম "মূল" java.lang.Number FormatException: ইনপুট স্ট্রিংয়ের জন্য: "9C001C21" java.lang এ। নাম্বার ফর্ম্যাট এক্সেকশন.ফর ইনপুটস্ট্রিং (অজানা উত্স)
রাফরাফ

(এটি Byte/ byteকেসের চেয়ে বেশি অদ্ভুত নয় : নেতৃত্ব ছাড়াই সর্বোচ্চ বিট সেট -)
গ্রেইবার্ড

2

আমি ক্যারেক্টার.ডিজিট সমাধানটি পছন্দ করি তবে এটি কীভাবে সমাধান করেছি তা এখানে

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 স্ট্রিমগুলির কাছে আপনার যদি অগ্রাধিকার থাকে তবে এটি কেবল জেডিকে আদিম ব্যবহার করে অর্জন করা যেতে পারে।

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()যদি আপনি সংক্রামক কিছু মনে না করেন সংগ্রাহক CONCATENATE ফাংশনে প্যারামিটার বাদ দেওয়া যেতে পারে 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;
}

যেমন পিএইচপি হেক্স 2bin () ফাংশন কিন্তু জাভা শৈলী।

উদাহরণ:

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" তারপরে এফএফ (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
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.