日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

java hex 编码_1-Hex编码

發布時間:2023/12/15 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java hex 编码_1-Hex编码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

編碼原理

Hex編碼就是把一個8位的字節數據用兩個十六進制數展示出來,編碼時,將8位二進制碼重新分組成兩個4位的字節,其中一個字節的低4位是原字節的高四位,另一個字節的低4位是原數據的低4位,高4位都補0,然后輸出這兩個字節對應十六進制數字作為編碼。Hex編碼后的長度是源數據的2倍,Hex編碼的編碼表為

0 0 1 1 2 2 3 3

4 4 5 5 6 6 7 7

8 8 9 9 10 a 11 b

12 c 13 d 14 e 15 f

比如ASCII碼A的Hex編碼過程為

ASCII碼:A (65)

二進制碼:0100_0001

重新分組:0000_0100 0000_0001

十六進制: 4 1

Hex編碼:41

e4b881

代碼實現

使用Bouncy Castle的實現

下面的代碼使用開源軟件Bouncy Castle實現Hex編解碼,使用的版本是1.56。

import java.io.UnsupportedEncodingException;

import org.bouncycastle.util.encoders.Hex;

public class HexTestBC {

public static void main(String[] args)

throws UnsupportedEncodingException {

// 編碼

byte data[] = "A".getBytes("UTF-8");

byte[] encodeData = Hex.encode(data);

String encodeStr = Hex.toHexString(data);

System.out.println(new String(encodeData, "UTF-8"));

System.out.println(encodeStr);

// 解碼

byte[] decodeData = Hex.decode(encodeData);

byte[] decodeData2 = Hex.decode(encodeStr);

System.out.println(new String(decodeData, "UTF-8"));

System.out.println(new String(decodeData2, "UTF-8"));

}

}

程序輸出

41

41

A

A

使用Apache Commons Codec實現

下面的代碼使用開源軟件Apache Commons Codec實現Hex編解碼,使用的版本是1.10。

import java.io.UnsupportedEncodingException;

import org.apache.commons.codec.DecoderException;

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

public class HexTestCC {

public static void main(String[] args)

throws UnsupportedEncodingException,

DecoderException {

// 編碼

byte data[] = "A".getBytes("UTF-8");

char[] encodeData = Hex.encodeHex(data);

String encodeStr = Hex.encodeHexString(data);

System.out.println(new String(encodeData));

System.out.println(encodeStr);

// 解碼

byte[] decodeData = Hex.decodeHex(encodeData);

System.out.println(new String(decodeData, "UTF-8"));

}

}

源碼分析

Bouncy Castle實現源碼分析

Bouncy Castle實現Hex編解碼的是org.bouncycastle.util.encoders.HexEncoder類,實現編碼時首先定義了一個編碼表

protected final byte[] encodingTable =

{

(byte)'0', (byte)'1', (byte)'2', (byte)'3',

(byte)'4', (byte)'5', (byte)'6', (byte)'7',

(byte)'8', (byte)'9', (byte)'a', (byte)'b',

(byte)'c', (byte)'d', (byte)'e', (byte)'f'

};

然后編碼的代碼是

public int encode(

byte[] data,

int off,

int length,

OutputStream out)

throws IOException

{

for (int i = off; i < (off + length); i++)

{

int v = data[i] & 0xff;

out.write(encodingTable[(v >>> 4)]);

out.write(encodingTable[v & 0xf]);

}

return length * 2;

}

解碼的實現稍微復雜一點,在HexEncoder的構造方法中會調用initialiseDecodingTable建立解碼表,代碼如下

protected final byte[] decodingTable = new byte[128];

protected void initialiseDecodingTable()

{

for (int i = 0; i < decodingTable.length; i++)

{

decodingTable[i] = (byte)0xff;

}

for (int i = 0; i < encodingTable.length; i++)

{

decodingTable[encodingTable[i]] = (byte)i;

}

decodingTable['A'] = decodingTable['a'];

decodingTable['B'] = decodingTable['b'];

decodingTable['C'] = decodingTable['c'];

decodingTable['D'] = decodingTable['d'];

decodingTable['E'] = decodingTable['e'];

decodingTable['F'] = decodingTable['f'];

}

解碼表是一個長度是128的字節數組,每個位置代表對應的ASCII碼,該位置上的值表示該ASCII碼對應的二進制碼。具體到Hex的解碼表,第48-59個位置,即ASCII碼0-9的位置保存了數字0-9,第65-70個位置,即ASCII碼A-F的位置保存了數字10-15,第97-102個位置,即ASCII碼a-f同樣保存了數字10-15。解碼表為

比如array[65] = A

-1 -1 -1 -1 -1 -1 -1 -1

-1 -1 -1 -1 -1 -1 -1 -1

-1 -1 -1 -1 -1 -1 -1 -1

-1 -1 -1 -1 -1 -1 -1 -1

-1 ! -1 " -1 # -1 $ -1 % -1 & -1 ' -1

( -1 ) -1 * -1 + -1 , -1 - -1 . -1 / -1

0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7

8 8 9 9 : -1 ; -1 < -1 = -1 > -1 ? -1

@ -1 A 10 B 11 C 12 D 13 E 14 F 15 G -1

H -1 I -1 J -1 K -1 L -1 M -1 N -1 O -1

P -1 Q -1 R -1 S -1 T -1 U -1 V -1 W -1

X -1 Y -1 Z -1 [ -1 \ -1 ] -1 ^ -1 _ -1

` -1 a 10 b 11 c 12 d 13 e 14 f 15 g -1

h -1 i -1 j -1 k -1 l -1 m -1 n -1 o -1

p -1 q -1 r -1 s -1 t -1 u -1 v -1 w -1

x -1 y -1 z -1 { -1 | -1 } -1 ~ -1 -1

解碼的過程實際上就是獲取連續兩個字節,取這兩個字節解碼表中對應的數值,然后將這兩個數值拼接成一個8位二進制碼,作為解碼的輸出。源碼如下:

public int decode(

byte[] data,

int off,

int length,

OutputStream out)

throws IOException

{

byte b1, b2;

int outLen = 0;

int end = off + length;

while (end > off)

{

if (!ignore((char)data[end - 1]))

{

break;

}

end--;

}

int i = off;

while (i < end)

{

while (i < end && ignore((char)data[i]))

{

i++;

}

b1 = decodingTable[data[i++]];

while (i < end && ignore((char)data[i]))

{

i++;

}

b2 = decodingTable[data[i++]];

if ((b1 | b2) < 0)

{

throw new IOException("invalid

characters encountered in Hex data");

}

out.write((b1 << 4) | b2);

outLen++;

}

return outLen;

}

其中ignore方法的代碼如下,解碼時會忽略首、尾及中間的空白。

private static boolean ignore(

char c)

{

return c == '\n' || c =='\r' || c == '\t' || c == ' ';

}

示例代碼中的Hex工具類持有HexEncoder的實例,并通過ByteArrayOutputStream類實現對byte數組的操作,此外不再贅述。

public class Hex

{

private static final Encoder encoder = new HexEncoder();

public static byte[] encode(

byte[] data,

int off,

int length)

{

ByteArrayOutputStream bOut = new ByteArrayOutputStream();

try

{

encoder.encode(data, off, length, bOut);

}

catch (Exception e)

{

throw new EncoderException("exception encoding Hex string: "

+ e.getMessage(), e);

}

return bOut.toByteArray();

}

......

}

Apache Commons Codec實現源碼分析

Apache Commons Codec實現Hex編碼的步驟是直接創建一個兩倍源數據長度的字符數組,然后分別將源數據的每個字節轉換成兩個字節放到目標字節數組中,Apache Commons Codec支持設置的要轉換為大寫還是小寫。

private static final char[] DIGITS_LOWER =

{'0', '1', '2', '3', '4', '5', '6', '7',

'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

private static final char[] DIGITS_UPPER =

{'0', '1', '2', '3', '4', '5', '6', '7',

'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

public static char[] encodeHex(final byte[] data) {

return encodeHex(data, true);

}

public static char[] encodeHex(final byte[] data,

final boolean toLowerCase) {

return encodeHex(data,

toLowerCase ? DIGITS_LOWER : DIGITS_UPPER);

}

protected static char[] encodeHex(final byte[] data,

final char[] toDigits) {

final int l = data.length;

final char[] out = new char[l << 1];

// two characters form the hex value.

for (int i = 0, j = 0; i < l; i++) {

out[j++] = toDigits[(0xF0 & data[i]) >>> 4];

out[j++] = toDigits[0x0F & data[i]];

}

return out;

}

Apache Commons Codec實現Hex解碼的步驟是首先創建一個原字符串一半長度的字節數組,然后依次將兩個連續的十六進制數轉換為一個字節數據,轉換時使用了JDK的Character.digit方法。

public static byte[] decodeHex(final char[] data)

throws DecoderException {

final int len = data.length;

if ((len & 0x01) != 0) {

throw new DecoderException("Odd number of characters.");

}

final byte[] out = new byte[len >> 1];

// two characters form the hex value.

for (int i = 0, j = 0; j < len; i++) {

int f = toDigit(data[j], j) << 4;

j++;

f = f | toDigit(data[j], j);

j++;

out[i] = (byte) (f & 0xFF);

}

return out;

}

protected static int toDigit(final char ch, final int index)

throws DecoderException {

final int digit = Character.digit(ch, 16);

if (digit == -1) {

throw new DecoderException(""

+ "Illegal hexadecimal character "

+ ch + " at index " + index);

}

return digit;

}

總結

以上是生活随笔為你收集整理的java hex 编码_1-Hex编码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。