converting a hex string back to a string, in Java - java

I am struggling trying to convert a hex number string back to the original string. I convert the string using the following method:
private static String hex(String binStr) {
String newStr = new String();
try {
String hexStr = "0123456789ABCDEF";
byte [] p = binStr.getBytes();
for(int k=0; k < p.length; k++ ){
int j = ( p[k] >> 4 )&0xF;
newStr = newStr + hexStr.charAt( j );
j = p[k]&0xF;
newStr = newStr + hexStr.charAt( j ) + " ";
}
} catch (Exception e) {
System.out.println("Failed to convert into hex values: " + e);
}
return newStr;
}
I am really stuck, and any advice would be greatly appreciated.
Thank you in advance

Consider this:
String hexStr = "0123456789ABCDEF";
long i = Long.valueOf(hexStr, 16);
System.out.println(Long.toHexString(i));

The code in the question destroys information. Only the most significant two bits and the least significant four bits of each input byte contribute to the result. That means it cannot, in general, be reversed.
If the right shift had been by four bits, instead of 6:
int j = ( p[k] >> 4 )&0xF;
all the input would have been preserved, and the original string could have been recovered from the hex string. Maybe you really meant the four bit shift?

Related

Convert a String Value to ASCII

I want to take the value of a ASCII value(Saved as a string) and convert it to the character to reveal a message. I tried this and it keeps throwing an index out of bound at the declaration of the int b.It also shows that str and b do not have a value
String value = "104 101 108 108 111";
char[] ch = new char[value.length()];
for (int i = 0; i < value.length(); i++) {
ch[i] = value.charAt(i);
}
System.out.println(ch.length);
String ans = "";
int i = 0;
while (i+2 < ch.length) {
int b= ch[i]+ch[i++]+ch[i+2];
String str = new Character((char) b).toString();
System.out.println(str);
System.out.println(b);
ans = ans+str;
i=i+3;
}
Using string split function
String value = "104 101 108 108 111";
String[] arrOfStr = value.split(" ");
String ans = "";
for(String str : arrOfStr) {
String str1 = Character.toString((char)Integer.parseInt(str));
ans += str1;
}
System.out.println(ans); // output: hello
We can switch the Imperative code to Declarative code using Java 8 Streams.
Key points to observe:
Declarative style is more readable and easy to write.
String Joiner is faster than simple String Concatenation.
No need to write an iterator.
import java.util.Arrays;
public class Main {
public static void main(String[] args) {
String value = "104 101 108 108 111";
Arrays.stream(value.split(" ")) // Starting a stream of String[]
.mapToInt(Integer::parseInt) // mapping String to int
.mapToObj(Character::toChars) // finding ASCII char from int
.forEach(System.out::print); // printing each character
}
}
If you wish to store the result and then print it, this is how is done.
import java.util.Arrays;
import java.util.stream.Collectors;
public class Main {
public static void main(String[] args) {
String value = "104 101 108 108 111";
String result = Arrays.stream(value.split(" ")) // Starting a stream of String[]
.mapToInt(Integer::parseInt) // mapping String to int
.mapToObj(Character::toChars) // finding ASCII char from int
.map(String::new) // convert char to String
.collect(Collectors.joining()); // combining individual result using String Joiner
System.out.println(result);
}
}
Comments to code:
There is a built-in method for for getting a char[] with the characters of a string, so the following two blocks of code are the same:
// Code from question
char[] ch = new char[value.length()];
for (int i = 0; i < value.length(); i++) {
ch[i] = value.charAt(i);
}
// Using built-in method
char[] ch = value.toCharArray();
It is better to use a for loop when increment a value while looping. The following two ways of writing the loop behave the same, but the for loop keeps the loop logic together:
// Code from question
int i = 0;
while (i+2 < ch.length) {
// some code here
i=i+3;
}
// Using for loop
for (int i = 0; i + 2 < ch.length; i=i+3) {
// some code here
}
The following line of code is entirely wrong:
int b= ch[i]+ch[i++]+ch[i+2];
i++ increments the value is i, but it is the value before the increment that is used in the expression, which means that if i = 0 before the line, the result is the same as this code:
int b = ch[0] + ch[0] + ch[2];
i = i + 1;
You need to replace i++ with i + 1, and realize that those are not the same.
Since you no longer increment the value of i by 1 in that statement, the loop much be changed from i=i+3 to i = i + 4, to correctly skip the spaces in the input.
The value of ch[i] is a char value, which is widened to an int value by the use of the + operator. The int value of a char is the Unicode Code Point value, which for your text is also the same as the ASCII code for the character.
This means that if i = 0, the expression would (after fixing issue #1) evaluate as:
int b = ch[0] + ch[1] + ch[2];
int b = `1` + `0` + `4`;
int b = 49 + 48 + 52;
int b = 149;
That matches the output from running the code is in question, where the second printed number is 149 (after fixing issue #1).
What you really wanted was to get the substring "104" and convert that to a number, then cast that ASCII code value to a char, like this:
String numberStr = value.substring(i, i + 3); // E.g. "104"
int number = Integer.parseInt(numberStr); // E.g. 104
String str = String.valueOf((char) number); // E.g. "h"
With that, you no longer need the char[], so the final code would be:
String value = "104 101 108 108 111";
String ans = "";
for (int i = 0; i + 2 < value.length(); i += 4) {
String numberStr = value.substring(i, i + 3);
int number = Integer.parseInt(numberStr);
String str = String.valueOf((char) number);
ans = ans + str;
}
System.out.println(ans);
Output
hello

Converting a reversed Hexadecimal String to Decimal [duplicate]

This question already has answers here:
Converting some hexadecimal string to a decimal integer
(13 answers)
Closed 4 years ago.
I am currently writing a program that reads the ID of NFC Tags and reverses them. The thing I am trying to accomplish now is to convert that reversed ID from Hex to Dec
Let's say that the ID of the number would be "3bde4eac", so the reversed result would be "ac4edb3b"
And I don't really know how to correctly convert that HexString to Decimal.
Here is my current code:
else{
String tagInfo = tag.toString() + "\n";
tagInfo = "";
byte[] tagId = tag.getId();
for(int i=n; i<tagId.length; i++){
tagInfo += Integer.toHexString(tagId[i] & 0xFF);
}
String s = tagInfo;
StringBuilder result = new StringBuilder();
for(int n = 0; n <=s.length()-2; n=n+2) {
result.append(new StringBuilder(s.substring(n, n + 2)).reverse());
}
s = result.reverse().toString();
Long f = Long.parseLong(s, 16);
textViewInfo.setText(s);
}
EDIT: Using the "duplicate link", I was able to solve the problem.
I changed the last part of my code to
s = result.reverse().toString();
Long g = hex2decimal(s);
textViewInfo.setText(g.toString());
With the function
public static Long hex2decimal(String s) {
String digits = "0123456789ABCDEF";
s = s.toUpperCase();
long val = 0;
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
long d = digits.indexOf(c);
val = 16*val + d;
}
return val;
}
You should try parsing the reversed string as hexadecimal and then convert the obtained int value to decimal. Check out Integer.parseInt(strValue, 16) to parse String in base16/hexadecimal and Integer.toString(intValue) for this.

Why can't I store Japanese UTF-8 characters in char array in Java?

I have a string "1234567(Asics (アシックスワーキング) )". It has unicode character, some are a part of ASCII and some are not. What java does is that it takes one byte for ASCII character and two bytes for other unicode characters.
Some part of my program is unable to process the string in this format. So I wanted to encode the values into escaped sequences.
So the string
"1234567(Asics (アシックスワーキング) )"
would map to
"\u0031\u0032\u0033\u0034\u0035\u0036\u0037\u0028\u0041\u0073\u0069\u0063\u0073\u0020\u0028\u30a2\u30b7\u30c3\u30af\u30b9\u30ef\u30fc\u30ad\u30f3\u30b0\u0029\u0020\u0029"
.
I wrote this function to do this :-
public static String convertToEscaped(String utf8) throws java.lang.Exception
{
char[] str = utf8.toCharArray();
StringBuilder unicodeStringBuilder = new StringBuilder();
for(int i = 0; i < str.length; i++){
char charValue = str[i];
int intValue = (int) charValue;
String hexValue = Integer.toHexString(intValue);
unicodeStringBuilder.append("\\u");
for (int length = hexValue.length(); length < 4; length++) {
unicodeStringBuilder.append("0");
}
unicodeStringBuilder.append(hexValue);
}
return unicodeStringBuilder.toString();
}
This was working fine outside of my program but caused issues inside my program. This was happening to the line char[] str = utf8.toCharArray();
Somehow I was loosing my japanese unicode characters and this was happening because t was dividing these characters into 2 in the char array.
So I decided to go with byte [] instead.
public static String convertToEscaped(String utf8) throws java.lang.Exception
{
byte str[] = utf8.getBytes();
StringBuilder unicodeStringBuilder = new StringBuilder();
for(int i = 0; i < str.length - 1 ; i+=2){
int intValue = (int) str[i]* 256 + (int)str[i+1];
String hexValue = Integer.toHexString(intValue);
unicodeStringBuilder.append("\\u");
for (int length = hexValue.length(); length < 4; length++) {
unicodeStringBuilder.append("0");
}
unicodeStringBuilder.append(hexValue);
}
return unicodeStringBuilder.toString();
}
Output :
\u3132\u3334\u3536\u3738\u2841\u7369\u6373\u2028\uffffe282\uffffa1e3\uffff81b7\uffffe283\uffff82e3\uffff81af\uffffe282\uffffb8e3\uffff82af\uffffe283\uffffbbe3\uffff81ad\uffffe283\uffffb2e3\uffff81b0\u2920
But this is also wrong as I am merging two single byte characters into one. What can I do to overcome this?
I don't know your other code's specific requirements. But my advice is to not reinvent the wheel and use the built-in encoding capabilities of the API.
For instance call getBytes with either StandardCharsets.UTF_16BE or StandardCharsets.UTF_16LE based on the endian-ness you need:
String s = "1234567(Asics (アシックスワーキング) )";
byte[] utf8 = s.getBytes(StandardCharsets.UTF_8);
byte[] utf16 = s.getBytes(StandardCharsets.UTF_16BE); // high order byte first
System.out.println(s.length()); // 28
System.out.println(utf8.length); // 48
System.out.println(utf16.length); // 56 (2 bytes for each char)
As they commented above the internal representation of string in java is utf-16. Found
Character.codePointAt() and Integer.toHexString() that are helpful in your case.
Renamed the parameter to just theString, also removed the throws Exception clause from your original method since no exception was thrown. (it is bad practice in general to throw these generic exceptions)
public static String convertToEscaped(String theString) {
char[] charArr = theString.toCharArray();
StringBuilder sb = new StringBuilder();
for (int i = 0; i < charArr.length; i++) {
String hexString = Integer.toHexString(Character.codePointAt(charArr, i));
sb.append("\\u");
if (hexString.length() == 2) {
sb.append("00");
}
sb.append(hexString);
}
return sb.toString();
}

Flip a Hex String

Acording to a other question made here Split a Hex String without spaces and flip it, I write this new question more clearly here.
I have an Hex String like this:
Hex_string = 2B00FFEC
What I need is to change the order of the Hex String to start from the latest characters, so this would be like this:
Fliped_hex_string = ECFF002B
In the other question I asked a way to achieve this using the .split() method. But there should be another way to get this in a better way.
As simple as you can is
String s = "2B00FFEC";
StringBuilder result = new StringBuilder();
for (int i = 0; i <=s.length()-2; i=i+2) {
result.append(new StringBuilder(s.substring(i,i+2)).reverse());
}
System.out.println(result.reverse().toString()); //op :ECFF002B
OP constrains the character length to exactly 8 characters in comments.
A purely numeric answer (inspired from idioms to convert endianness); saves going to and from strings
n is an int:
int m = ((n>>24)&0xff) | // byte 3 to byte 0
((n<<8)&0xff0000) | // byte 1 to byte 2
((n>>8)&0xff00) | // byte 2 to byte 1
((n<<24)&0xff000000); // byte 0 to byte 3
If you need to convert this to hexadecimal, use
String s = Integer.toHexString(m);
and if you need to set n from hexadecimal, use
int n = (int)Long.parseLong(hex_string, 16);
where hex_string is your initial string. You need to go via the Long parser to allow for negatives.
You could do something like:
String a = "456789AB";
char[] ca = a.toCharArray();
StringBuilder sb = new StringBuilder(a.length());
for (int i = 0; i<a.length();i+=2)
{
sb.insert(0, ca, i, 2);
}
This also extends to longer Strings if needed
Perhaps you should try something as simple as this:
public static String flip(final String hex){
final StringBuilder builder = new StringBuilder(hex.length());
for(int i = hex.length(); i > 1; i-=2)
builder.append(hex.substring(i-2, i));
return builder.toString();
}
public static void main(String args[]){
System.out.println(flip("2B00FFEC"));
}
The output is: ECFF002B
Next time you ask a question, perhaps you should show us some code you've written used in order to solve your problem (and then ask us why your code doesn't work, not your problem). You will not learn anything from us just providing answers without you knowing how they work.
This method seems to do what you want
String changeHexOrder(String s) {
char[] arr = s.toCharArray();
char tmp;
//change positions of [i, i + 1 , , , , , ,length - i - 2, length - i - 1]
for (int i = 0; i < arr.length / 2; i += 2) {
tmp = arr[i];
arr[i] = arr[arr.length-i-2];
arr[arr.length-i-2] = tmp;
tmp = arr[i+1];
arr[i+1] = arr[arr.length-i-1];
arr[arr.length-i-1] = tmp;
}
return new String(arr);
}
This worked for me
StringBuilder lsbToMsb=new StringBuilder();
for(int i=input.length();i>0;i-=2)
{
lsbMsb.append(lsbToMsb.substring(i-2,i));
}
String lsbMsb=lsbMsb.toString();

Left padding a String with Zeros [duplicate]

This question already has answers here:
How can I pad a String in Java?
(32 answers)
Closed 5 years ago.
I've seen similar questions here and here.
But am not getting how to left pad a String with Zero.
input: "129018"
output: "0000129018"
The total output length should be TEN.
If your string contains numbers only, you can make it an integer and then do padding:
String.format("%010d", Integer.parseInt(mystring));
If not I would like to know how it can be done.
String paddedString = org.apache.commons.lang.StringUtils.leftPad("129018", 10, "0")
the second parameter is the desired output length
"0" is the padding char
This will pad left any string to a total width of 10 without worrying about parse errors:
String unpadded = "12345";
String padded = "##########".substring(unpadded.length()) + unpadded;
//unpadded is "12345"
//padded is "#####12345"
If you want to pad right:
String unpadded = "12345";
String padded = unpadded + "##########".substring(unpadded.length());
//unpadded is "12345"
//padded is "12345#####"
You can replace the "#" characters with whatever character you would like to pad with, repeated the amount of times that you want the total width of the string to be. E.g. if you want to add zeros to the left so that the whole string is 15 characters long:
String unpadded = "12345";
String padded = "000000000000000".substring(unpadded.length()) + unpadded;
//unpadded is "12345"
//padded is "000000000012345"
The benefit of this over khachik's answer is that this does not use Integer.parseInt, which can throw an Exception (for example, if the number you want to pad is too large like 12147483647). The disadvantage is that if what you're padding is already an int, then you'll have to convert it to a String and back, which is undesirable.
So, if you know for sure that it's an int, khachik's answer works great. If not, then this is a possible strategy.
String str = "129018";
String str2 = String.format("%10s", str).replace(' ', '0');
System.out.println(str2);
String str = "129018";
StringBuilder sb = new StringBuilder();
for (int toPrepend=10-str.length(); toPrepend>0; toPrepend--) {
sb.append('0');
}
sb.append(str);
String result = sb.toString();
You may use apache commons StringUtils
StringUtils.leftPad("129018", 10, "0");
https://commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/apache/commons/lang/StringUtils.html#leftPad(java.lang.String,%20int,%20char)
To format String use
import org.apache.commons.lang.StringUtils;
public class test {
public static void main(String[] args) {
String result = StringUtils.leftPad("wrwer", 10, "0");
System.out.println("The String : " + result);
}
}
Output : The String : 00000wrwer
Where the first argument is the string to be formatted, Second argument is the length of the desired output length and third argument is the char with which the string is to be padded.
Use the link to download the jar http://commons.apache.org/proper/commons-lang/download_lang.cgi
If you need performance and know the maximum size of the string use this:
String zeroPad = "0000000000000000";
String str0 = zeroPad.substring(str.length()) + str;
Be aware of the maximum string size. If it is bigger then the StringBuffer size, you'll get a java.lang.StringIndexOutOfBoundsException.
An old question, but I also have two methods.
For a fixed (predefined) length:
public static String fill(String text) {
if (text.length() >= 10)
return text;
else
return "0000000000".substring(text.length()) + text;
}
For a variable length:
public static String fill(String text, int size) {
StringBuilder builder = new StringBuilder(text);
while (builder.length() < size) {
builder.append('0');
}
return builder.toString();
}
I prefer this code:
public final class StrMgr {
public static String rightPad(String input, int length, String fill){
String pad = input.trim() + String.format("%"+length+"s", "").replace(" ", fill);
return pad.substring(0, length);
}
public static String leftPad(String input, int length, String fill){
String pad = String.format("%"+length+"s", "").replace(" ", fill) + input.trim();
return pad.substring(pad.length() - length, pad.length());
}
}
and then:
System.out.println(StrMgr.leftPad("hello", 20, "x"));
System.out.println(StrMgr.rightPad("hello", 20, "x"));
Use Google Guava:
Maven:
<dependency>
<artifactId>guava</artifactId>
<groupId>com.google.guava</groupId>
<version>14.0.1</version>
</dependency>
Sample code:
Strings.padStart("129018", 10, '0') returns "0000129018"
Based on #Haroldo Macêdo's answer, I created a method in my custom Utils class such as
/**
* Left padding a string with the given character
*
* #param str The string to be padded
* #param length The total fix length of the string
* #param padChar The pad character
* #return The padded string
*/
public static String padLeft(String str, int length, String padChar) {
String pad = "";
for (int i = 0; i < length; i++) {
pad += padChar;
}
return pad.substring(str.length()) + str;
}
Then call Utils.padLeft(str, 10, "0");
Here's another approach:
int pad = 4;
char[] temp = (new String(new char[pad]) + "129018").toCharArray()
Arrays.fill(temp, 0, pad, '0');
System.out.println(temp)
Here's my solution:
String s = Integer.toBinaryString(5); //Convert decimal to binary
int p = 8; //preferred length
for(int g=0,j=s.length();g<p-j;g++, s= "0" + s);
System.out.println(s);
Output: 00000101
Right padding with fix length-10:
String.format("%1$-10s", "abc")
Left padding with fix length-10:
String.format("%1$10s", "abc")
Here is a solution based on String.format that will work for strings and is suitable for variable length.
public static String PadLeft(String stringToPad, int padToLength){
String retValue = null;
if(stringToPad.length() < padToLength) {
retValue = String.format("%0" + String.valueOf(padToLength - stringToPad.length()) + "d%s",0,stringToPad);
}
else{
retValue = stringToPad;
}
return retValue;
}
public static void main(String[] args) {
System.out.println("'" + PadLeft("test", 10) + "'");
System.out.println("'" + PadLeft("test", 3) + "'");
System.out.println("'" + PadLeft("test", 4) + "'");
System.out.println("'" + PadLeft("test", 5) + "'");
}
Output:
'000000test'
'test'
'test'
'0test'
The solution by Satish is very good among the expected answers. I wanted to make it more general by adding variable n to format string instead of 10 chars.
int maxDigits = 10;
String str = "129018";
String formatString = "%"+n+"s";
String str2 = String.format(formatString, str).replace(' ', '0');
System.out.println(str2);
This will work in most situations
int number = -1;
int holdingDigits = 7;
System.out.println(String.format("%0"+ holdingDigits +"d", number));
Just asked this in an interview........
My answer below but this (mentioned above) is much nicer->
String.format("%05d", num);
My answer is:
static String leadingZeros(int num, int digitSize) {
//test for capacity being too small.
if (digitSize < String.valueOf(num).length()) {
return "Error : you number " + num + " is higher than the decimal system specified capacity of " + digitSize + " zeros.";
//test for capacity will exactly hold the number.
} else if (digitSize == String.valueOf(num).length()) {
return String.valueOf(num);
//else do something here to calculate if the digitSize will over flow the StringBuilder buffer java.lang.OutOfMemoryError
//else calculate and return string
} else {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < digitSize; i++) {
sb.append("0");
}
sb.append(String.valueOf(num));
return sb.substring(sb.length() - digitSize, sb.length());
}
}
Check my code that will work for integer and String.
Assume our first number is 129018. And we want to add zeros to that so the the length of final string will be 10. For that you can use following code
int number=129018;
int requiredLengthAfterPadding=10;
String resultString=Integer.toString(number);
int inputStringLengh=resultString.length();
int diff=requiredLengthAfterPadding-inputStringLengh;
if(inputStringLengh<requiredLengthAfterPadding)
{
resultString=new String(new char[diff]).replace("\0", "0")+number;
}
System.out.println(resultString);
I have used this:
DecimalFormat numFormat = new DecimalFormat("00000");
System.out.println("Code format: "+numFormat.format(123));
Result: 00123
I hope you find it useful!

Categories