I converted a byte array into string by doing
String s = encryptedBytes1.toString();
String gh = convertStringToHex(s);
Then I printed on screen gh which is the hex form it returned this:
gh:[B#5985910
this is the function convert
public static String convertStringToHex(String str){
char[] chars = str.toCharArray();
StringBuffer hex = new StringBuffer();
for(int i = 0; i < chars.length; i++){
hex.append(Integer.toHexString((int)chars[i]));
}
return hex.toString();
}
Can any one help me printing the hex form string?
In general you can convert string and hex values (numbers) with the following functions:
String hexString1 = "0x20";
Integer integer = Integer.decode(hexString); // is 32
String hexString1 = String.toHexString(integer); // is "20"
Now you need to iterate over your byteArray/String.
EDIT: As you specified your question, please see this answer on SO. I guess it is the same problem: Converting A String To Hexadecimal In Java
encryptedBytes1.toString() is giving you a string representation of the object because all arrays are objects in Java it is not converting a byte array into a String.
I think that you are not converting your byte array to String properly. This works for me.
byte encryptedBytes1[] = "ABCDEFGHIK".getBytes();
String aux = new String(encryptedBytes1);
System.out.println(convertStringToHex(aux));
41 42 43 44 45 46 47 48 49 4b
Keep in mind that you may need to specify a charset and that the primitive data byte takes 1 byte and char(which is meant to contain a Unicode Character) takes 2.
Related
I am trying to parse an ascii list to a string. The problem is that with some special chars, I have torubles. If I try to parse this:
115 097 116 195 168 108 194 183 108 105 116
, the result sould be "satèl·lit". The code I am using to parse it is :
ASCIIList.add(Character.toString((char) Integer.parseInt(asciiValue)));
But the result is satèl·lit. I saw that for example "è" -> "195 168". I do not know how to parse it correctly.
Assuming you already have split the input into an array of string, the code could look like so:
String convertToString(String[] numberArray) {
byte[] utf8Bytes = new byte[numberArray.length];
for (int i = 0; i < numberArray.length; i++) {
utf8Bytes[i] = (byte) Integer.parseInt(numberArray[i]);
}
return new String(utf8Bytes, StandardCharsets.UTF_8);
}
So each number becomes a bytes. The entire array of bytes is then converted into a string using UTF-8 charset.
UTF-8 uses multiple bytes to represent characters outside the ASCII range. In your example it affects "è" and "·".
I've found method toHexString() but it converts string into hex, while the value is already converted (like "20 0F 01 etc."). What's the best way to get hex values from this String for later purposes (ex. adding, sending some of them to output device)?
Try
Integer.parseInt(String val, int radix)
Example
Integer.parseInt("-FF", 16) returns -255
https://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#parseInt(java.lang.String,%20int)
Use String.split() to break the string up into individual bytes, and Integer.parseInt(s, 16) to convert the string representation into an integer.
Something like this should work:
List<Integer> parseHex(String hex) {
ArrayList<Integer> a = new ArrayList<Integer>();
for (String s : hex.split("\\s+")) {
a.add(Integer.parseInt(s, 16));
}
return a;
}
Since you mention preferring a byte array, you can use a ByteBuffer to accumulate byte values:
String text = "20 0F 01";
ByteBuffer buffer = ByteBuffer.allocate((text.length() + 1) / 3);
Scanner scanner = new Scanner(text);
while (scanner.hasNextInt(16)) {
buffer.put((byte) scanner.nextInt(16));
}
byte[] bytes = buffer.array();
We use hasNextInt and nextInt, rather than hasNextByte and nextByte, because Java’s numeric types are signed, and values above 7f are not representable as signed bytes.
byte bytes[] = new byte[16];
random.nextBytes(bytes);
try {
return new String(bytes, "UTF-8");
} catch (UnsupportedEncodingException e) {
log.warn("Hash generation failed", e);
}
When I generate a String with given method, and when i apply string.getBytes().length it returns some other value. Max was 32. Why a 16 byte array ends up generating a another size byte string ?
But if i do string.length() it returns 16.
This is because your bytes are first converted to Unicode string, which attempts to create UTF-8 char sequence from these bytes. If a byte cannot be treated as ASCII char nor captured with next byte(s) to form legal unicode char, it is replaced by "�". Such char is transformed into 3 bytes when calling String#getBytes(), thus adding 2 extra bytes to resulting output.
If you're lucky to generate ASCII chars only, String#getBytes() will return 16-byte array, if no, resulting array may be longer. For example, the following code snippet:
byte[] b = new byte[16];
Arrays.fill(b, (byte) 190);
b = new String(b, "UTF-8").getBytes();
returns array of 48(!) bytes long.
Classical mistake born from the misunderstanding of the relationship between bytes and chars, so here we go again.
There is no 1-to-1 mapping between byte and char; it all depends on the character coding you use (in Java, that is a Charset).
Worse: given a byte sequence, it may or may not be encoded to a char sequence.
Try this for instance:
final byte[] buf = new byte[16];
new Random().nextBytes(buf);
final Charset utf8 = StandardCharsets.UTF_8;
final CharsetDecoder decoder = utf8.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT);
decoder.decode(ByteBuffer.wrap(buf));
This is very likely to throw a MalformedInputException.
I know this is not exactly an answer but then you didn't clearly explain your problem; and the example above shows already that you have the wrong understanding between what a byte is and what a char is.
The generated bytes might contain valid multibyte characters.
Take this as example. The string contains only one character, but as byte representation it take three bytes.
String s = "Ω";
System.out.println("length = " + s.length());
System.out.println("bytes = " + Arrays.toString(s.getBytes("UTF-8")));
String.length() return the length of the string in characters. The character Ω is one character whereas it's a 3 byte long in UTF-8.
If you change your code like this
Random random = new Random();
byte bytes[] = new byte[16];
random.nextBytes(bytes);
System.out.println("string = " + new String(bytes, "UTF-8").length());
System.out.println("string = " + new String(bytes, "ISO-8859-1").length());
The same bytes are interpreted with a different charset. And following the javadoc from String(byte[] b, String charset)
The length of the new String is a function of the charset, and hence may
not be equal to the length of the byte array.
If you look at the string you're producing, most of the random bytes you're generating do not form valid UTF-8 characters. The String constructor, therefore, replaces them with the unicode 'REPLACEMENT CHARACTER' �, which takes up 3 bytes, 0xFFFD.
As an example:
public static void main(String[] args) throws UnsupportedEncodingException
{
Random random = new Random();
byte bytes[] = new byte[16];
random.nextBytes(bytes);
printBytes(bytes);
final String s = new String(bytes, "UTF-8");
System.out.println(s);
printCharacters(s);
}
private static void printBytes(byte[] bytes)
{
for (byte aByte : bytes)
{
System.out.print(
Integer.toHexString(Byte.toUnsignedInt(aByte)) + " ");
}
System.out.println();
}
private static void printCharacters(String s)
{
s.codePoints().forEach(i -> System.out.println(Character.getName(i)));
}
On a given run, I got this output:
30 41 9b ff 32 f5 38 ec ef 16 23 4a 54 26 cd 8c
0A��2�8��#JT&͌
DIGIT ZERO
LATIN CAPITAL LETTER A
REPLACEMENT CHARACTER
REPLACEMENT CHARACTER
DIGIT TWO
REPLACEMENT CHARACTER
DIGIT EIGHT
REPLACEMENT CHARACTER
REPLACEMENT CHARACTER
SYNCHRONOUS IDLE
NUMBER SIGN
LATIN CAPITAL LETTER J
LATIN CAPITAL LETTER T
AMPERSAND
COMBINING ALMOST EQUAL TO ABOVE
String.getBytes().length is likely to be longer, as it counts bytes needed to represent the string, while length() counts 2-byte code units.
read more here
This will try to create a String assuming the bytes are in UTF-8.
new String(bytes, "UTF-8");
This in general will go horribly wrong as UTF-8 multi-byte sequences can be invalid.
Like:
String s = new String(new byte[] { -128 }, StandardCharsets.UTF_8);
The second step:
byte[] bytes = s.getBytes();
will use the platform encoding (System.getProperty("file.encoding")). Better specify it.
byte[] bytes = s.getBytes(StandardCharsets.UTF_8);
One should realize, internally String will maintain Unicode, an array of 16-bit char in UTF-16.
One should entirely abstain from using String for byte[]. It will always involve a conversion, cost double memory and be error prone.
I have this program:
String hexadecimal = "AF";
byte decimal[] = new byte[hexadecimal.length()/2];
int j = 0;
for ( int i = 0; i < decimal.length; i++)
{
decimal[i] = (byte) Integer.parseInt(hexadecimal.substring(j,j+2),16); //Maybe the problem is this statement
j = j + 2;
}
String s = new String(decimal);
System.out.println("TOTAL LEN: " + s.length());
byte aux[] = s.getBytes();
System.out.println("TOTAL LEN: " + aux.length);
The first total is "1" and the second one is "3", i thought i would will get "1" in the second total. Why is happen this? My intention is generate another hexadecimal string with the same value as the original string (AF), but i am having this issue.
Regards!
P.D. Sorry for my english, let me know if i explained myself well.
Don't know what exactly you try to achieve. But find below what you are doing.
Integer.parseInt(hexadecimal.substring(j, j + 2), 16) returns 175
(byte) 175 is -81
new String(decimal) tries to create an String from this byte array related to your current character set (probably it's UTF-8)
As the byte array does not contain a valid representation of UTF-8 bytes the created String contains the "REPLACEMENT CHARACTER" for the Unicode codepoint U+FFFD. The UTF-8 byte representation for this codepoint is EF BF BD (or -17 -65 -67). That's why the second length is three.
Have a look here Wikipedia UTF-8. Any character with a codepoint <= 7F can be represented by a single byte. For all other characters the first byte must have the bits 7 and 6 set 11....... Which is not the case for the value -81 which is 10101111. There for this is not a valid codepoint and it's replaced with the "REPLACEMENT CHARACTER".
I have a String which contains hex values. Now i want to write this exact string to a file with the ending .hex . How can i realize this in java?
I already tried to convert the Hex Values into ASCII and then write this string into a file.
But all Hex Values which are higher then 127(dec) can't be processed correctly.
86(hex) is transformed to ?(char), which is 3F(hex) and not 86(hex).
You can try to take each char of your string, convert it to integer and then write values in bytes in a file. To do the opposite process, you just have to read the file into a byte array and convert each byte into a char to retrieve your string. Then I'm sure you can find some algorithm to cast your string into Hex string.
For me the Answer was this:
Under Projectproperties i needed to set the Text-file-Encoding to ISO-8859-1.
Then my old procedure worked very well.
public static String hexToASCII(String hex){
if(hex.length()%2 != 0){
System.err.println("requires EVEN number of chars");
return null;
}
StringBuilder sb = new StringBuilder();
for( int i=0; i < hex.length()-1; i+=2 ){
String output = hex.substring(i, (i + 2));
int decimal = Integer.parseInt(output, 16);
sb.append((char)decimal);
}
return sb.toString();
}