Convert char array to byte array and vice versa

I want to convert a Java char array to an array of bytes without creating an intermediate String , since the char array contains a password. I looked through several methods, but all of them seem to fail:

 char[] password = "password".toCharArray(); byte[] passwordBytes1 = new byte[password.length*2]; ByteBuffer.wrap(passwordBytes1).asCharBuffer().put(password); byte[] passwordBytes2 = new byte[password.length*2]; for(int i=0; i<password.length; i++) { passwordBytes2[2*i] = (byte) ((password[i]&0xFF00)>>8); passwordBytes2[2*i+1] = (byte) (password[i]&0x00FF); } String passwordAsString = new String(password); String passwordBytes1AsString = new String(passwordBytes1); String passwordBytes2AsString = new String(passwordBytes2); System.out.println(passwordAsString); System.out.println(passwordBytes1AsString); System.out.println(passwordBytes2AsString); assertTrue(passwordAsString.equals(passwordBytes1) || passwordAsString.equals(passwordBytes2)); 

The statement always fails (and, critically, when the code is used in the production process, the password is rejected), but print statements print the password three times. Why are passwordBytes1AsString and passwordBytes2AsString different from passwordAsString but seem identical? Am I missing a null terminator or something else? What can I do to make the conversion and cancellation work?

+34
java arrays char byte
Feb 08 '11 at 10:25
source share
8 answers

The problem is using the String(byte[]) constructor String(byte[]) , which uses standard platform encoding. This is almost never what you should do - if you pass UTF-16 as the character encoding for the job, your tests are likely to pass. Currently, I suspect that passwordBytes1AsString and passwordBytes2AsString are 16 characters long, with each other being U + 0000.

+12
Feb 08 2018-11-11T00:
source share

Converting between char and byte - encoding and decoding a character set. I prefer to make this as clear as possible in the code. This does not mean additional code:

  Charset latin1Charset = Charset.forName("ISO-8859-1"); charBuffer = latin1Charset.decode(ByteBuffer.wrap(byteArray)); // also decode to String byteBuffer = latin1Charset.encode(charBuffer); // also decode from String 

To the side:

The java.nio classes and the java.io Reader / Writer classes use ByteBuffer and CharBuffer (which use bytes [] and char [] as support arrays). Therefore, it is often preferable to use these classes directly. However, you can always:
  byteArray = ByteBuffer.array(); byteBuffer = ByteBuffer.wrap(byteArray); byteBuffer.get(byteArray); charBuffer.put(charArray); charArray = CharBuffer.array(); charBuffer = ByteBuffer.wrap(charArray); charBuffer.get(charArray); charBuffer.put(charArray); 
+10
May 01 '13 at 4:11
source share

If you want to use ByteBuffer and CharBuffer, do not make a simple .asCharBuffer() that just does UTF-16 (LE or BE, depending on your system), you can set the byte order with order ) (since Java strings and, hence your char[] internally uses this encoding).

Use Charset.forName(charsetName) and then its encode or decode or newEncoder / newDecoder .

When converting your byte [] to String, you must also specify the encoding (and it must be the same).

+4
Feb 08 '11 at 10:50
source share

I would do this using a loop to convert to bytes, and another to return to char.

 char[] chars = "password".toCharArray(); byte[] bytes = new byte[chars.length*2]; for(int i=0;i<chars.length;i++) { bytes[i*2] = (byte) (chars[i] >> 8); bytes[i*2+1] = (byte) chars[i]; } char[] chars2 = new char[bytes.length/2]; for(int i=0;i<chars2.length;i++) chars2[i] = (char) ((bytes[i*2] << 8) + (bytes[i*2+1] & 0xFF)); String password = new String(chars2); 
+4
Feb 08 '11 at 11:30
source share

You should use getBytes() instead of toCharArray()

Replace string

 char[] password = "password".toCharArray(); 

from

 byte[] password = "password".getBytes(); 
+2
Jul 20 2018-12-12T00:
source share

This is a continuation of Peter Lowry's answer. In order for the inverse transform (bytes to characters) to work correctly for the entire range of characters, the code should be as follows:

 char[] chars = new char[bytes.length/2]; for (int i = 0; i < chars.length; i++) { chars[i] = (char) (((bytes[i*2] & 0xff) << 8) + (bytes[i*2+1] & 0xff)); } 

We need an "unsign" byte before using ( & 0xff ). Otherwise, half of all possible char values ​​will return incorrectly. For example, characters in the range [0x80..0xff] will be affected.

+2
Mar 12 '14 at 10:40
source share
  public byte[] charsToBytes(char[] chars){ Charset charset = Charset.forName("UTF-8"); ByteBuffer byteBuffer = charset.encode(CharBuffer.wrap(chars)); return Arrays.copyOf(byteBuffer.array(), byteBuffer.limit()); } public char[] bytesToChars(byte[] bytes){ Charset charset = Charset.forName("UTF-8"); CharBuffer charBuffer = charset.decode(ByteBuffer.wrap(bytes)); return Arrays.copyOf(charBuffer.array(), charBuffer.limit()); } 
+2
May 16 '17 at 8:40
source share

When you use GetBytes From String in Java, the return result will depend on the default encoding of your computer (for example: StandardCharsetsUTF-8 or StandardCharsets.ISO_8859_1etc ...).

So, whenever you want getBytes from a String object. Be sure to specify the encoding. eg:

 String sample = "abc"; Byte[] a_byte = sample .getBytes(StandardCharsets.UTF_8); 

Check what happened to the code. In java, a string called sample is stored in Unicode. each char in String, stored for 2 bytes.

 sample : value: "abc" in Memory(Hex): 00 61 00 62 00 63 a -> 00 61 b -> 00 62 c -> 00 63 

But, when we get Bytes From String, we have

 Byte[] a_byte = sample .getBytes(StandardCharsets.UTF_8) //result is : 61 62 63 //length: 3 bytes Byte[] a_byte = sample .getBytes(StandardCharsets.UTF_16BE) //result is : 00 61 00 62 00 63 //length: 6 bytes 

To get a single byte of a string. We can just read the string memory and get every byte of String.Below - this is an example code:

 public static byte[] charArray2ByteArray(char[] chars){ int length = chars.length; byte[] result = new byte[length*2+2]; int i = 0; for(int j = 0 ;j<chars.length;j++){ result[i++] = (byte)( (chars[j] & 0xFF00) >> 8 ); result[i++] = (byte)((chars[j] & 0x00FF)) ; } return result; } 

Customs:

 String sample = "abc"; //First get the chars of the String,each char has two bytes(Java). Char[] sample_chars = sample.toCharArray(); //Get the bytes byte[] result = charArray2ByteArray(sample_chars). //Back to String. //Make sure we use UTF_16BE. Because we read the memory of Unicode of //the String from Left to right. That the same reading //sequece of UTF-16BE. String sample_back= new String(result , StandardCharsets.UTF_16BE); 
+1
Jan 15 '16 at 3:33
source share



All Articles