La conversion char tableau en tableau d'octets et de retour à nouveau
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 passwordBytes1AsString
et passwordBytes2AsString
différente de passwordAsString
, pourtant, semblent identiques? Ai-je raté un terminateur null ou quelque chose? Que puis-je faire pour faire la conversion et unconversion travail?
- Pourquoi voulez-Vous éviter de créer un intermédiaire de la Chaîne?
- Soleil le recommande en tant que meilleure pratique: download.oracle.com/javase/1.5.0/docs/guide/security/jce/... les Chaînes de caractères sont immuables, et ne peut donc pas être remis à zéro, comme des tableaux de char - au lieu de cela, votre mot de passe traîne dans la mémoire pour une période de temps indéterminée.
Vous devez vous connecter pour publier un commentaire.
Le problème est l'utilisation de la
String(byte[])
constructeur, qui utilise la plate-forme de codage par défaut. C'est presque jamais ce que vous devez faire, si vous passez en "UTF-16", comme l'encodage des caractères de travail, vos tests seront probablement passer. Actuellement je soupçonne quepasswordBytes1AsString
etpasswordBytes2AsString
sont chaque 16 caractères de long, avec tous les autres caractères U+0000.String passwordBytes1AsString = new String(passwordBytes1, "UTF-16");
) et il n'y a pas de changement. J'ai aussi essayé de vérifier la longueur des chaînes -String.length()
retourne 8. Serait-il compter U+0000 personnages?equals()
dans l'affirmation. *facepalm* l'original de Votre supposition était effectivement la bonne. Merci beaucoup.De Conversion entre char et de l'octet jeu de caractères d'encodage et de décodage.Je préfère la rendre aussi claire que possible dans le code. Il ne veut pas vraiment dire un code supplémentaire de volume:
De côté:
java.nio classes et java.io Lecteur/enregistreur de classes utilisent ByteBuffer & CharBuffer (qui utilisent byte[] et char[] que la sauvegarde de tableaux). Donc souvent préférable si vous utilisez ces classes directement. Cependant, vous pouvez toujours le faire:
Réponse Originale À Cette Question
Modifiées à utiliser StandardCharsets
Ici est un JavaDoc page pour StandardCharsets.
Noter dans la JavaDoc de la page:
Si vous souhaitez utiliser un ByteBuffer et CharBuffer, ne pas faire de la simple
.asCharBuffer()
, qui est tout simplement un UTF-16 (LE ou ÊTRE, selon votre système, vous pouvez définir l'ordre des octets avec laorder
méthode) à la conversion (depuis les Cordes de Java et donc votrechar[]
utilise en interne ce codage).Utilisation
Charset.forName(charsetName)
, et puis saencode
oudecode
méthode, ou lanewEncoder
/newDecoder
.Lors de la conversion de votre byte[] à la Chaîne, vous devez également indiquer l'encodage (et il devrait être le même).
Je voudrais faire est d'utiliser une boucle pour convertir des octets et un autre pour conver retour à char.
Vous devriez faire usage de
getBytes()
au lieu detoCharArray()
Remplacer la ligne
avec
String#getBytes()
sans spécifier un encodage, qui vous amène dans tous les types de portabilité de la difficulté.C'est une extension de Peter Lawrey de réponse. Afin d'en arrière (octets de caractères) de conversion de fonctionner correctement pour l'ensemble de la gamme de caractères, le code doit être comme suit:
Nous avons besoin de "unsign" octets avant de l'utiliser (
& 0xff
). Sinon la moitié de tous les possibles char valeurs n'obtiendrez pas correctement. Par exemple, les caractères au sein[0x80..0xff]
gamme seront touchés.Lorsque vous utilisez GetBytes à Partir d'une Chaîne de caractères en Java, Le résultat dépendra de la valeur par défaut encoder de votre ordinateur.(par exemple: StandardCharsetsUTF-8 ou StandardCharsets.ISO_8859_1etc...).
Donc, chaque fois que vous voulez getBytes à partir d'un Objet de type String. Assurez-vous de donner un encoder . comme :
Laisser vérifier ce qui s'est passé avec le code.
En java, la Chaîne nommée échantillon est stocké par Unicode. tous les caractères dans une Chaîne enregistrée par 2 octets.
Mais, Lorsque nous getBytes à Partir d'une Chaîne, nous avons
Afin d'obtenir le oringle octet de la Chaîne. Il nous suffit de lire la Mémoire de la chaîne et obtenir de Chaque octet de la Chaîne.Ci-dessous est un exemple de Code:
Usages:
getBytes
, donc ce n'est pas vraiment pertinent. Êtes-vous essayer de commenter l'un de l'autre des réponses?