Is it possible to convert a byte array to a string but where the length of the string is exactly the same length as the number of bytes in the array? If I use the following:
byte[] data; // Fill it with data
data.toString();
The length of the string is different than the length of the array. I believe that this is because Java and/or Android takes some kind of default encoding into account. The values in the array can be negative as well. Theoretically it should be possible to convert any byte to some character. I guess I need to figure out how to specify an encoding that generates a fixed single byte width for each character.
EDIT:
I tried the following but it didn't work:
byte[] textArray; // Fill this with some text.
String textString = new String(textArray, "ASCII");
textArray = textString.getBytes("ASCII"); // textArray ends up with different data.
You can use the String constructor String(byte[] data) to create a string from the byte array. If you want to specify the charset as well, you can use String(byte[] data, Charset charset) constructor.
Try your code sample with US-ASCII or ISO-8859-1 in place of ASCII. ASCII is not a built-in Character encoding for Java or Android, but one of those two are. They are guaranteed single-byte encodings, with a caveat that characters not in the character set will be silently truncated.
This should work fine!
public static byte[] stringToByteArray(String pStringValue){
int length= pStringValue.length();
byte[] bytes = new byte[length];
for(int index=0; index<length; index++){
char ch= pStringValue.charAt(index);
bytes[index]= (byte)ch;
}
return bytes;
}
since JDK 1.6:
You can also use:
stringValue.getBytes() which will return you a byte array.
In case of passing a NULL string, you need to handle that by either throwing the nullPointerException or handling it inside the method itself.
Related
I have a function for hashing passwords, that returns a byte[] with entries using the full range of the byte datatype from -128 to 127. I have tried to convert the byte[] to a String using new String(byte_array, StandardCharsets.UTF_8);. This does return a String - however it can not properly encode negative numbers - hence it encodes them to a "�" character. When comparing two of those characters using: new String(new byte[]{-1}, StandardCharsets.UTF_8).equals(new String(new byte[]{-2}, StandardCharsets.UTF_8)) it turns out the String representation for all negative numbers is equal as the expression above returns true. While this doesn't fully ruin my hashing functionality as the hash of the same expression will still always yield the same result, this is obviously not what I want as it increases the chance of two different inputs yielding the same output drastically.
Is there some easy fix for this or any alternative idea how to convert the byte[] to a String? For context I want to use the String to later write it to a file to store it in a file and later read it again to compare it to other hashes.
Edit: After a bit of trying around with the tips from the comments my solution is to convert the byte[] to a char[] and add 128 to every value. The char array can then easily be converted to a String or be written to a file directly (byteHash is the byte[]):
char[] charHash = new char[byteHash.length];
for(int i = 0; i < byteHash.length; i++){
charHash[i] = (char) (byteHash[i]+128);
}
return new String(charHash);
I do not really like the solution but it works.
The appropriate solution to this is to use an encoding like hexadecimal (https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/HexFormat.html) or Base64 (https://docs.oracle.com/javase/8/docs/api/java/util/Base64.html) to convert an arbitrary byte sequence to a string reversibly.
I have an enum
public enum Test {
VALUE, NAME;
}
I convert it into a byte array
byte[] array = Test.VALUE.toString().getBytes(Charsets.UTF_8)
how can i convert that back into an enum?
Test.valueOf(array.toString()) does not work.
The reason why array.toString didn't work is that toString returns a description of the array, not the string constructed using the bytes in the array with UTF-8 encoding. toString just returns something like [B#60e53b93 which means practically nothing to humans.
To convert a byte array to a string, use the string's constructor, the one that takes a byte array and a Charset. Here's the whole code:
// converting to byte array
Test t = Test.VALUE;
byte[] bytes = t.toString().getBytes(StandardCharsets.UTF_8);
// converting back to Test
String str = new String(bytes, StandardCharsets.UTF_8);
Test newT = Test.valueOf(str);
If you think about it logically, toString can't possibly give you what you expect. This is because to convert a byte array to a string, you need to specify an encoding! You obvious did not pass a Charset object when you call toString, so how on earth is the computer going to know what charset you want?
You have to convert the array back to a proper String first using it constructor. array.toString() does not do what you think and will only return gibberish.
byte[] array = Test.VALUE.toString().getBytes(Charsets.UTF_8);
String valueString = new String(array, Charsets.UTF_8);
Test value = Test.valueOf(valueString);
I'm writing a web application in Google app Engine. It allows people to basically edit html code that gets stored as an .html file in the blobstore.
I'm using fetchData to return a byte[] of all the characters in the file. I'm trying to print to an html in order for the user to edit the html code. Everything works great!
Here's my only problem now:
The byte array is having some issues when converting back to a string. Smart quotes and a couple of characters are coming out looking funky. (?'s or japanese symbols etc.) Specifically it's several bytes I'm seeing that have negative values which are causing the problem.
The smart quotes are coming back as -108 and -109 in the byte array. Why is this and how can I decode the negative bytes to show the correct character encoding?
The byte array contains characters in a special encoding (that you should know). The way to convert it to a String is:
String decoded = new String(bytes, "UTF-8"); // example for one encoding type
By The Way - the raw bytes appear may appear as negative decimals just because the java datatype byte is signed, it covers the range from -128 to 127.
-109 = 0x93: Control Code "Set Transmit State"
The value (-109) is a non-printable control character in UNICODE. So UTF-8 is not the correct encoding for that character stream.
0x93 in "Windows-1252" is the "smart quote" that you're looking for, so the Java name of that encoding is "Cp1252". The next line provides a test code:
System.out.println(new String(new byte[]{-109}, "Cp1252"));
Java 7 and above
You can also pass your desired encoding to the String constructor as a Charset constant from StandardCharsets. This may be safer than passing the encoding as a String, as suggested in the other answers.
For example, for UTF-8 encoding
String bytesAsString = new String(bytes, StandardCharsets.UTF_8);
You can try this.
String s = new String(bytearray);
public class Main {
/**
* Example method for converting a byte to a String.
*/
public void convertByteToString() {
byte b = 65;
//Using the static toString method of the Byte class
System.out.println(Byte.toString(b));
//Using simple concatenation with an empty String
System.out.println(b + "");
//Creating a byte array and passing it to the String constructor
System.out.println(new String(new byte[] {b}));
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
new Main().convertByteToString();
}
}
Output
65
65
A
public static String readFile(String fn) throws IOException
{
File f = new File(fn);
byte[] buffer = new byte[(int)f.length()];
FileInputStream is = new FileInputStream(fn);
is.read(buffer);
is.close();
return new String(buffer, "UTF-8"); // use desired encoding
}
I suggest Arrays.toString(byte_array);
It depends on your purpose. For example, I wanted to save a byte array exactly like the format you can see at time of debug that is something like this : [1, 2, 3] If you want to save exactly same value without converting the bytes to character format, Arrays.toString (byte_array) does this,. But if you want to save characters instead of bytes, you should use String s = new String(byte_array). In this case, s is equal to equivalent of [1, 2, 3] in format of character.
The previous answer from Andreas_D is good. I'm just going to add that wherever you are displaying the output there will be a font and a character encoding and it may not support some characters.
To work out whether it is Java or your display that is a problem, do this:
for(int i=0;i<str.length();i++) {
char ch = str.charAt(i);
System.out.println(i+" : "+ch+" "+Integer.toHexString(ch)+((ch=='\ufffd') ? " Unknown character" : ""));
}
Java will have mapped any characters it cannot understand to 0xfffd the official character for unknown characters. If you see a '?' in the output, but it is not mapped to 0xfffd, it is your display font or encoding that is the problem, not Java.
Here below is how I generate a SecureRandom:
byte[] arr = SecureRandom.getInstance("SHA1PRNG").generateSeed(32);
then, I convert it to a string like this:
String str = new String(arr)
and finally, I try to convert the string back to my original byte array:
byte[] arr2 = str.getBytes()
The problem is that the last statement does not return my original byte array... Am I missing something?
then, I convert it to a string like this:
Don't do that!
You have two problems here:
this constructor will use the default encoding;
even if you used UTF-8 as an encoding, some byte sequences just cannot be encoded to chars!
You should not use String to hold binary data; or use a string-based encoding, such as Base64.
For more information, see CharsetDecoder and CodingErrorAction.
This is simply to error check my code, but I would like to convert a single byte out of a byte array to a string. Does anyone know how to do this? This is what I have so far:
recBuf = read( 5 );
Log.i( TAG, (String)recBuf[0] );
But of course this doesn't work.
I have googled around a bit but have only found ways to convert an entire byte[] array to a string...
new String( recBuf );
I know I could just do that, and then sift through the string, but it would make my task easier if I knew how to operate this way.
You can make a new byte array with a single byte:
new String(new byte[] { recBuf[0] })
Use toString method of Byte
String s=Byte.toString(recBuf[0] );
Try above , it works.
Example:
byte b=14;
String s=Byte.toString(b );
System.out.println("String value="+ s);
Output:
String value=14
There's a String constructor of the form String(byte[] bytes, int offset, int length). You can always use that for your conversion.
So, for example:
byte[] bite = new byte[]{65,67,68};
for(int index = 0; index < bite.length; index++)
System.out.println(new String(bite, index,1));
What about converting it to char? or simply
new String(buffer[0])
public static String toString (byte value)
Since: API Level 1
Returns a string containing a concise, human-readable description of the specified byte value.
Parameters
value the byte to convert to a string.
Returns
a printable representation of value.]1
this is how you can convert single byte to string try code as per your requirement
Edit:
Hows about
""+ recBuf[0];//Hacky... not sure if would work
((Byte)recBuf[0]).toString();
Pretty sure that would work.
Another alternate could be converting byte to char and finally string
Log.i(TAG, Character.toString((char) recBuf[0]));
Or
Log.i(TAG, String.valueOf((char) recBuf[0]));
You're assuming that you're using 8bit character encoding (like ASCII) and this would be wrong for many others.
But with your assumption you might just as well using simple cast to character like
char yourChar = (char) yourByte;
or if really need String:
String string = String.valueOf((char)yourByte);