40 votes

Conversion de tableau de caractères en tableau d'octets et inversement

Je suis à la recherche pour convertir un Java char tableau dans un tableau d'octets sans la création d'un intermédiaire String, comme le char tableau contient un mot de passe. J'ai regardé un couple de méthodes, mais ils semblent tous à l'échec:

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));

L'assertion échoue toujours (et, de façon critique, lorsque le code est utilisé dans la production, le mot de passe est rejeté), mais les instructions d'impression, d'imprimer le mot de passe trois fois. Pourquoi sont - passwordBytes1AsString et passwordBytes2AsString différent de passwordAsString, mais semblent identiques? Ai-je raté un terminateur null ou quelque chose? Que puis-je faire pour faire la conversion et unconversion travail?

16voto

Glen Best Points 11455

La conversion entre le caractère et l'octet est un encodage et un décodage de jeu de caractères. Je préfère le rendre aussi clair que possible dans le code. Cela ne signifie pas vraiment un volume de code supplémentaire:

  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
 

De côté:

Les classes java.nio et java.io Reader / Writer utilisent ByteBuffer & CharBuffer (qui utilisent byte [] et char [] comme tableaux de sauvegarde). Si souvent préférable si vous utilisez ces classes directement. Cependant, vous pouvez toujours faire:

  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);
 

12voto

Jon Skeet Points 692016

Le problème est votre utilisation du constructeur String(byte[]) , qui utilise l'encodage par défaut de la plate-forme. Ce n'est presque jamais ce que vous devriez faire - si vous passez "UTF-16" comme codage de caractères pour fonctionner, vos tests réussiront probablement. Actuellement, je soupçonne que passwordBytes1AsString et passwordBytes2AsString ont chacun 16 caractères, chaque autre caractère étant U + 0000.

5voto

Peter Lawrey Points 229686

Je ferais est d'utiliser une boucle pour convertir en octets et une autre pour reconvertir en 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);
 

4voto

Paŭlo Ebermann Points 35526

Si vous souhaitez utiliser un ByteBuffer et CharBuffer, ne pas faire de la simple .asCharBuffer(), ce qui est tout simplement un UTF-16 (LE ou ÊTRE, selon votre système, vous pouvez définir l'ordre des octets avec l' order méthode de conversion (depuis les Cordes de Java et donc votre char[] en interne utilise ce codage).

Utiliser Charset.forName(charsetName), puis de son encode ou decode méthode, ou l' newEncoder /newDecoder.

Lors de la conversion de votre byte[] à la Chaîne, vous devez également indiquer l'encodage (et il devrait être le même).

2voto

yoda Points 11

Vous devez utiliser getBytes() au lieu de toCharArray()

Remplacez la ligne

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

avec

 byte[] password = "password".getBytes();
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X