Skip to content

Commit b3607d8

Browse files
committed
[CODEC-73] Hex: Make string2byte conversions indepedent of platform default encoding.
Also refactor DigestUtils to call a new method on Hex. git-svn-id: https://svn.apache.org/repos/asf/commons/proper/codec/trunk@801391 13f79535-47bb-0310-9956-ffa450edef68
1 parent bade1b7 commit b3607d8

6 files changed

Lines changed: 339 additions & 165 deletions

File tree

src/java/org/apache/commons/codec/binary/Hex.java

Lines changed: 149 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -17,48 +17,49 @@
1717

1818
package org.apache.commons.codec.binary;
1919

20+
import java.io.UnsupportedEncodingException;
21+
2022
import org.apache.commons.codec.BinaryDecoder;
2123
import org.apache.commons.codec.BinaryEncoder;
24+
import org.apache.commons.codec.CharEncoding;
2225
import org.apache.commons.codec.DecoderException;
2326
import org.apache.commons.codec.EncoderException;
2427

2528
/**
26-
* Hex encoder and decoder.
29+
* Hex encoder and decoder. The charset used for certain operation can be set, the default is set in
30+
* {@link #DEFAULT_CHARSET_NAME}
2731
*
2832
* @since 1.1
2933
* @author Apache Software Foundation
3034
* @version $Id$
3135
*/
3236
public class Hex implements BinaryEncoder, BinaryDecoder {
3337

34-
/**
35-
* Used to build output as Hex
38+
/**
39+
* Default charset name is {@link CharEncoding#UTF_8}
3640
*/
37-
private static final char[] DIGITS_LOWER = {
38-
'0', '1', '2', '3', '4', '5', '6', '7',
39-
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
40-
};
41+
public static final String DEFAULT_CHARSET_NAME = CharEncoding.UTF_8;
4142

42-
/**
43-
* Used to build output as Hex
43+
/**
44+
* Used to build output as Hex
4445
*/
45-
private static final char[] DIGITS_UPPER = {
46-
'0', '1', '2', '3', '4', '5', '6', '7',
47-
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
48-
};
46+
private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
4947

5048
/**
51-
* Converts an array of characters representing hexadecimal values into an
52-
* array of bytes of those same values. The returned array will be half the
53-
* length of the passed array, as it takes two characters to represent any
54-
* given byte. An exception is thrown if the passed char array has an odd
55-
* number of elements.
49+
* Used to build output as Hex
50+
*/
51+
private static final char[] DIGITS_UPPER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
52+
53+
/**
54+
* Converts an array of characters representing hexadecimal values into an array of bytes of those same values. The
55+
* returned array will be half the length of the passed array, as it takes two characters to represent any given
56+
* byte. An exception is thrown if the passed char array has an odd number of elements.
5657
*
57-
* @param data An array of characters containing hexadecimal digits
58-
* @return A byte array containing binary data decoded from
59-
* the supplied char array.
60-
* @throws DecoderException Thrown if an odd number or illegal of characters
61-
* is supplied
58+
* @param data
59+
* An array of characters containing hexadecimal digits
60+
* @return A byte array containing binary data decoded from the supplied char array.
61+
* @throws DecoderException
62+
* Thrown if an odd number or illegal of characters is supplied
6263
*/
6364
public static byte[] decodeHex(char[] data) throws DecoderException {
6465

@@ -82,22 +83,6 @@ public static byte[] decodeHex(char[] data) throws DecoderException {
8283
return out;
8384
}
8485

85-
/**
86-
* Converts a hexadecimal character to an integer.
87-
*
88-
* @param ch A character to convert to an integer digit
89-
* @param index The index of the character in the source
90-
* @return An integer
91-
* @throws DecoderException Thrown if ch is an illegal hex character
92-
*/
93-
protected static int toDigit(char ch, int index) throws DecoderException {
94-
int digit = Character.digit(ch, 16);
95-
if (digit == -1) {
96-
throw new DecoderException("Illegal hexadecimal charcter " + ch + " at index " + index);
97-
}
98-
return digit;
99-
}
100-
10186
/**
10287
* Converts an array of bytes into an array of characters representing the hexadecimal values of each byte in order.
10388
* The returned array will be double the length of the passed array, as it takes two characters to represent any
@@ -151,35 +136,87 @@ protected static char[] encodeHex(byte[] data, char[] toDigits) {
151136
}
152137

153138
/**
154-
* Converts an array of character bytes representing hexadecimal values into an
155-
* array of bytes of those same values. The returned array will be half the
156-
* length of the passed array, as it takes two characters to represent any
157-
* given byte. An exception is thrown if the passed char array has an odd
158-
* number of elements.
139+
* Converts an array of bytes into a String representing the hexadecimal values of each byte in order. The returned
140+
* String will be double the length of the passed array, as it takes two characters to represent any given byte.
141+
*
142+
* @param data
143+
* a byte[] to convert to Hex characters
144+
* @return A String containing hexadecimal characters
145+
* @since 1.4
146+
*/
147+
public static String encodeHexString(byte[] data) {
148+
return new String(encodeHex(data));
149+
}
150+
151+
/**
152+
* Converts a hexadecimal character to an integer.
159153
*
160-
* @param array An array of character bytes containing hexadecimal digits
161-
* @return A byte array containing binary data decoded from
162-
* the supplied byte array (representing characters).
163-
* @throws DecoderException Thrown if an odd number of characters is supplied
164-
* to this function
154+
* @param ch
155+
* A character to convert to an integer digit
156+
* @param index
157+
* The index of the character in the source
158+
* @return An integer
159+
* @throws DecoderException
160+
* Thrown if ch is an illegal hex character
161+
*/
162+
protected static int toDigit(char ch, int index) throws DecoderException {
163+
int digit = Character.digit(ch, 16);
164+
if (digit == -1) {
165+
throw new DecoderException("Illegal hexadecimal charcter " + ch + " at index " + index);
166+
}
167+
return digit;
168+
}
169+
170+
private String charsetName = DEFAULT_CHARSET_NAME;
171+
172+
/**
173+
* Creates a new codec with the default charset name {@link #DEFAULT_CHARSET_NAME}
174+
*/
175+
public Hex() {
176+
// use default encoding
177+
}
178+
179+
/**
180+
* Creates a new codec with the given charset name.
181+
*
182+
* @param csName
183+
* the charset name.
184+
*/
185+
public Hex(String csName) {
186+
setCharsetName(csName);
187+
}
188+
189+
/**
190+
* Converts an array of character bytes representing hexadecimal values into an array of bytes of those same values.
191+
* The returned array will be half the length of the passed array, as it takes two characters to represent any given
192+
* byte. An exception is thrown if the passed char array has an odd number of elements.
193+
*
194+
* @param array
195+
* An array of character bytes containing hexadecimal digits
196+
* @return A byte array containing binary data decoded from the supplied byte array (representing characters).
197+
* @throws DecoderException
198+
* Thrown if an odd number of characters is supplied to this function
165199
* @see #decodeHex(char[])
166200
*/
167201
public byte[] decode(byte[] array) throws DecoderException {
168-
return decodeHex(new String(array).toCharArray());
202+
try {
203+
return decodeHex(new String(array, getCharsetName()).toCharArray());
204+
} catch (UnsupportedEncodingException e) {
205+
throw new DecoderException(e.getMessage(), e);
206+
}
169207
}
170-
208+
171209
/**
172-
* Converts a String or an array of character bytes representing hexadecimal values into an
173-
* array of bytes of those same values. The returned array will be half the
174-
* length of the passed String or array, as it takes two characters to represent any
175-
* given byte. An exception is thrown if the passed char array has an odd
176-
* number of elements.
210+
* Converts a String or an array of character bytes representing hexadecimal values into an array of bytes of those
211+
* same values. The returned array will be half the length of the passed String or array, as it takes two characters
212+
* to represent any given byte. An exception is thrown if the passed char array has an odd number of elements.
177213
*
178-
* @param object A String or, an array of character bytes containing hexadecimal digits
179-
* @return A byte array containing binary data decoded from
180-
* the supplied byte array (representing characters).
181-
* @throws DecoderException Thrown if an odd number of characters is supplied
182-
* to this function or the object is not a String or char[]
214+
* @param object
215+
* A String or, an array of character bytes containing hexadecimal digits
216+
* @return A byte array containing binary data decoded from the supplied byte array (representing characters).
217+
* @throws DecoderException
218+
* Thrown if an odd number of characters is supplied to this function or the object is not a String or
219+
* char[]
183220
* @see #decodeHex(char[])
184221
*/
185222
public Object decode(Object object) throws DecoderException {
@@ -192,38 +229,73 @@ public Object decode(Object object) throws DecoderException {
192229
}
193230

194231
/**
195-
* Converts an array of bytes into an array of bytes for the characters representing the
196-
* hexadecimal values of each byte in order. The returned array will be
197-
* double the length of the passed array, as it takes two characters to
232+
* Converts an array of bytes into an array of bytes for the characters representing the hexadecimal values of each
233+
* byte in order. The returned array will be double the length of the passed array, as it takes two characters to
198234
* represent any given byte.
199-
*
200-
* @param array a byte[] to convert to Hex characters
235+
* <p>
236+
* The conversion from hexadecimal characters to the returned bytes is performed with the charset named by
237+
* {@link #getCharsetName()}.
238+
* </p>
239+
*
240+
* @param array
241+
* a byte[] to convert to Hex characters
201242
* @return A byte[] containing the bytes of the hexadecimal characters
243+
* @throws IllegalStateException
244+
* if the charsetName is invalid. This API throws {@link IllegalStateException} instead of
245+
* {@link UnsupportedEncodingException} for backward compatibility.
202246
* @see #encodeHex(byte[])
203247
*/
204248
public byte[] encode(byte[] array) {
205-
return new String(encodeHex(array)).getBytes();
249+
return StringUtils.getBytesUnchecked(encodeHexString(array), getCharsetName());
206250
}
207251

208252
/**
209-
* Converts a String or an array of bytes into an array of characters representing the
210-
* hexadecimal values of each byte in order. The returned array will be
211-
* double the length of the passed String or array, as it takes two characters to
212-
* represent any given byte.
213-
*
214-
* @param object a String, or byte[] to convert to Hex characters
253+
* Converts a String or an array of bytes into an array of characters representing the hexadecimal values of each
254+
* byte in order. The returned array will be double the length of the passed String or array, as it takes two
255+
* characters to represent any given byte.
256+
* <p>
257+
* The conversion from hexadecimal characters to bytes to be encoded to performed with the charset named by
258+
* {@link #getCharsetName()}.
259+
* </p>
260+
*
261+
* @param object
262+
* a String, or byte[] to convert to Hex characters
215263
* @return A char[] containing hexadecimal characters
216-
* @throws EncoderException Thrown if the given object is not a String or byte[]
264+
* @throws EncoderException
265+
* Thrown if the given object is not a String or byte[]
217266
* @see #encodeHex(byte[])
218267
*/
219-
public Object encode(Object object) throws EncoderException {
268+
public Object encode(Object object) throws EncoderException {
220269
try {
221-
byte[] byteArray = object instanceof String ? ((String) object).getBytes() : (byte[]) object;
270+
byte[] byteArray = object instanceof String ? ((String) object).getBytes(getCharsetName()) : (byte[]) object;
222271
return encodeHex(byteArray);
223272
} catch (ClassCastException e) {
224273
throw new EncoderException(e.getMessage(), e);
274+
} catch (UnsupportedEncodingException e) {
275+
throw new EncoderException(e.getMessage(), e);
225276
}
226277
}
227278

228-
}
279+
/**
280+
* Gets the charset name.
281+
*
282+
* @return the charset name.
283+
*/
284+
public String getCharsetName() {
285+
return this.charsetName;
286+
}
287+
288+
/**
289+
* Sets the charset name.
290+
*
291+
* @param charsetName
292+
* the charset name.
293+
*/
294+
public void setCharsetName(String charsetName) {
295+
this.charsetName = charsetName;
296+
}
229297

298+
public String toString() {
299+
return super.toString() + "[charsetName=" + this.charsetName + "]";
300+
}
301+
}

src/java/org/apache/commons/codec/binary/StringUtils.java

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,10 @@ public class StringUtils {
4343
* @throws IllegalStateException
4444
* Thrown when the charset is missing, which should be never according the the Java specification.
4545
* @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
46-
* @see #getSupportedBytes(String, String)
46+
* @see #getBytesUnchecked(String, String)
4747
*/
4848
public static byte[] getBytesIso8859_1(String string) {
49-
return StringUtils.getSupportedBytes(string, CharEncoding.ISO_8859_1);
49+
return StringUtils.getBytesUnchecked(string, CharEncoding.ISO_8859_1);
5050
}
5151

5252
/**
@@ -59,10 +59,10 @@ public static byte[] getBytesIso8859_1(String string) {
5959
* @throws IllegalStateException
6060
* Thrown when the charset is missing, which should be never according the the Java specification.
6161
* @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
62-
* @see #getSupportedBytes(String, String)
62+
* @see #getBytesUnchecked(String, String)
6363
*/
6464
public static byte[] getBytesUsAscii(String string) {
65-
return StringUtils.getSupportedBytes(string, CharEncoding.US_ASCII);
65+
return StringUtils.getBytesUnchecked(string, CharEncoding.US_ASCII);
6666
}
6767

6868
/**
@@ -75,10 +75,10 @@ public static byte[] getBytesUsAscii(String string) {
7575
* @throws IllegalStateException
7676
* Thrown when the charset is missing, which should be never according the the Java specification.
7777
* @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
78-
* @see #getSupportedBytes(String, String)
78+
* @see #getBytesUnchecked(String, String)
7979
*/
8080
public static byte[] getBytesUtf16(String string) {
81-
return StringUtils.getSupportedBytes(string, CharEncoding.UTF_16);
81+
return StringUtils.getBytesUnchecked(string, CharEncoding.UTF_16);
8282
}
8383

8484
/**
@@ -91,10 +91,10 @@ public static byte[] getBytesUtf16(String string) {
9191
* @throws IllegalStateException
9292
* Thrown when the charset is missing, which should be never according the the Java specification.
9393
* @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
94-
* @see #getSupportedBytes(String, String)
94+
* @see #getBytesUnchecked(String, String)
9595
*/
9696
public static byte[] getBytesUtf16Be(String string) {
97-
return StringUtils.getSupportedBytes(string, CharEncoding.UTF_16BE);
97+
return StringUtils.getBytesUnchecked(string, CharEncoding.UTF_16BE);
9898
}
9999

100100
/**
@@ -107,10 +107,10 @@ public static byte[] getBytesUtf16Be(String string) {
107107
* @throws IllegalStateException
108108
* Thrown when the charset is missing, which should be never according the the Java specification.
109109
* @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
110-
* @see #getSupportedBytes(String, String)
110+
* @see #getBytesUnchecked(String, String)
111111
*/
112112
public static byte[] getBytesUtf16Le(String string) {
113-
return StringUtils.getSupportedBytes(string, CharEncoding.UTF_16LE);
113+
return StringUtils.getBytesUnchecked(string, CharEncoding.UTF_16LE);
114114
}
115115

116116
/**
@@ -123,10 +123,10 @@ public static byte[] getBytesUtf16Le(String string) {
123123
* @throws IllegalStateException
124124
* Thrown when the charset is missing, which should be never according the the Java specification.
125125
* @see <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/nio/charset/Charset.html">Standard charsets</a>
126-
* @see #getSupportedBytes(String, String)
126+
* @see #getBytesUnchecked(String, String)
127127
*/
128128
public static byte[] getBytesUtf8(String string) {
129-
return StringUtils.getSupportedBytes(string, CharEncoding.UTF_8);
129+
return StringUtils.getBytesUnchecked(string, CharEncoding.UTF_8);
130130
}
131131

132132
/**
@@ -148,7 +148,7 @@ public static byte[] getBytesUtf8(String string) {
148148
* @see CharEncoding
149149
* @see String#getBytes(String)
150150
*/
151-
public static byte[] getSupportedBytes(String string, String charsetName) {
151+
public static byte[] getBytesUnchecked(String string, String charsetName) {
152152
if (string == null) {
153153
return null;
154154
}

0 commit comments

Comments
 (0)