2009-06-25 4 views
4

Ich habe vor kurzem begonnen, MD5-Hashing (in Java) zu betrachten, und während ich Algorithmen und Methoden gefunden habe, um mir dabei zu helfen, frage ich mich, wie es wirklich funktioniert.Kann jemand die Konvertierung von Bytearray zu Hexadezimalstring erklären?

Zum einen fand ich folgende von this URL:

private static String convertToHex(byte[] data) { 
    StringBuffer buf = new StringBuffer(); 
    for (int i = 0; i < data.length; i++) { 
     int halfbyte = (data[i] >>> 4) & 0x0F; 
     int two_halfs = 0; 
     do { 
      if ((0 <= halfbyte) && (halfbyte <= 9)) 
       buf.append((char) ('0' + halfbyte)); 
      else 
       buf.append((char) ('a' + (halfbyte - 10))); 
       halfbyte = data[i] & 0x0F; 
      } while(two_halfs++ < 1); 
     } 
    return buf.toString(); 
} 

Ich habe keine Notwendigkeit nicht gefunden Bitverschiebung in Java zu verwenden, so bin ich ein bisschen auf, dass rostig. Jemand, der gut genug ist, um zu illustrieren (in einfachen Worten), wie genau macht der obige Code die Konvertierung? ">>>"?

Ich fand auch andere Lösungen auf Stackoverflow, wie here und here, die BigInteger verwendet stattdessen:

Warum funktioniert das auch, und die Art und Weise ist effizienter?

Danke für Ihre Zeit.

Antwort

10
private static String convertToHex(byte[] data) { 
    StringBuffer buf = new StringBuffer(); 
    for (int i = 0; i < data.length; i++) { 

Bis zu diesem Punkt ... nur Basis-Set und eine Schleife beginnend durch alle Bytes im Array

 int halfbyte = (data[i] >>> 4) & 0x0F; 

Bytes zu gehen, wenn umgewandelt hex zwei hexadezimalen Ziffern oder 8 binären Ziffern sind je nachdem, welche Basis Sie Schauen Sie sich das an. Die obige Anweisung verschiebt die hohen 4 Bits nach unten (>>> ist vorzeichenlose Verschiebung nach rechts) und logisch UND verknüpft sie mit 0000 1111, so dass das Ergebnis eine Ganzzahl ist, die den hohen 4 Bits des Bytes entspricht (erste hexadezimale Zahl)).

Say 23 war ein Eingang, das ist 0001 0111 in binär. Die Verschiebung macht und logische UND coverts dies zu 0000 0001.

 int two_halfs = 0; 
     do { 

Dies ist nur die do einrichtet/while-Schleife zweimal laufen

  if ((0 <= halfbyte) && (halfbyte <= 9)) 
       buf.append((char) ('0' + halfbyte)); 
      else 
       buf.append((char) ('a' + (halfbyte - 10))); 

Hier sind wir die tatsächliche Hexadezimalzeichens Anzeige, im Grunde nur Verwenden Sie die Null oder ein Zeichen als Startpunkt und verschieben Sie bis zum richtigen Zeichen. Die erste if-Anweisung deckt alle Ziffern 0-9 ab, die zweite alle Ziffern 10-15 (af in hex)

Auch hier ist unser Beispiel 0000 0001 im Dezimalformat gleich 1. Wir werden im oberen Bereich gefangen Wenn block und add 1 zu dem '0' Zeichen, um das Zeichen '1' zu erhalten, hängen Sie das an die Zeichenfolge und weitermachen.

   halfbyte = data[i] & 0x0F; 

Jetzt richten wir die Ganzzahl so ein, dass sie nur den niedrigen Bits des Bytes entspricht und wiederholt.

Wieder, wenn unsere Eingabe 23 war ...0001 0111 nach dem logischen UND wird nur 0000 0111, was 7 in Dezimal ist. Wiederholen Sie die gleiche Logik wie oben und das Zeichen '7' wird angezeigt.

  } while(two_halfs++ < 1); 

Nun gehen wir einfach zum nächsten Byte im Array und wiederholen.

 } 
    return buf.toString(); 
} 

Um Ihre nächste Frage zu beantworten, verfügt die Java-API bereits über ein Basiskonvertierungsprogramm, das bereits in BigInteger integriert ist. Siehe die toString(int radix) Dokumentation.

Ich weiß nicht, welche Implementierung von der Java-API verwendet wird, kann ich nicht sicher sagen, aber ich würde wetten, dass die Java-Implementierung effizienter ist als der erste etwas einfache Algorithmus, den Sie gepostet haben.

+1

+1 für die Anstrengung und dafür, mich dazu zu schlagen. Die einzige Sache, die ich hinzufügen würde, ist ein Verweis auf die bitweise Operation Dokumentation: http://www.j2ee.me/docs/books/tutorial/java/nutsandbolts/op3.html – Welbog

+0

danke für diese Erklärung –

+0

Vielen Dank für die ausführliche Erklärung! – aberrant80

1

Für eine ausführliche Erklärung auf bitshifting die Antworten in der Frage SO folgenden Besuche What are bitwise shift (bit-shift) operators and how do they work?

Er scheint zu versuchen, ein einziges Byte in eine Zahl zu konvertieren kleiner als 16 ist, indem so kann er leicht Weicht caracther bestimmen dass Byte stellt mit dem Code

if ((0 <= halfbyte) && (halfbyte <= 9)) 
       buf.append((char) ('0' + halfbyte)); 
      else 
       buf.append((char) ('a' + (halfbyte - 10))); 

Dies ist eine simple Antwort, aber ich bin nicht so hell sowieso = D

2

dieses Bit zu beantworten:

Warum auch funktioniert das

nicht. Zumindest nicht so wie die Loop-Version. new BigInteger (...). toString (16) zeigt keine führenden Nullen, was die vorherige Version ist. Normalerweise für etwas wie das Schreiben eines Byte-Arrays (insbesondere eines, das etwas wie einen Hash repräsentiert), würden Sie eine Ausgabe fester Länge wünschen. Wenn Sie also diese Version verwenden möchten, müssen Sie sie entsprechend aufbereiten.

+0

Vielen Dank für den Unterschied. – aberrant80

0

Diese Sachen müssen Sie selbst nicht schreiben, weil es bereits in Apache-Commons-Codec steht geschrieben:

import org.apache.commons.codec.binary.Hex; 
... 
Hex.encodeHexString(byte[] array) 

eine Menge nützlicher Methoden in Hex Klasse Es gibt keine.