2011-04-19 9 views
17

Tengo un montón de cuerdas hexagonales, uno de ellos, por ejemplo, es:Java - analizar y cadena hexadecimal sin signo en una larga firmado

d1bc4f7154ac9edb 

que es el valor hexadecimal de "-3333702275990511909". Este es el mismo hex que obtienes si haces Long.toHexString ("d1bc4f7154ac9edb");

Por ahora, supongamos que solo tengo acceso a los valores de cadena hexadecimal y eso es todo. Hacer esto:

Long.parseLong(hexstring, 16); 

no funciona debido a que la convierte en un valor diferente que es demasiado grande para un largo. ¿Existe la posibilidad de convertir estos valores hexadecimales sin signo en largos firmados?

Gracias!

Respuesta

21

Puede utilizar BigInteger analizarlo y volver una long:

long value = new BigInteger("d1bc4f7154ac9edb", 16).longValue(); 
System.out.println(value); // this outputs -3333702275990511909 
+2

Sólo una nota para los visitantes de hoy: como observa de Scott Carey, a partir de Java 8 podemos hacer simplemente 'Long.parseUnsignedLong (hexstring, 16)', por lo fresco :) – NIA

5

Usted puede dividir por la mitad y leer 32 bits a la vez. Luego use shift-left por 32 y una lógica o para volver a ponerlo en una única longitud.

+0

tiene usted un ejemplo de código ¿A qué te refieres? – Peter

+2

Algo así como: (Long.parseLong (hexstring.substring (0, 8), 16) << 32) | (Long.parseLong (hexstring.substring (8, 16), 16) << 0) –

4

El siguiente método tiene la ventaja de no crear otro objeto BigInteger cada vez que necesite hacer esto.

public class Test { 
    /** 
    * Returns a {@code long} containing the least-significant 64 bits of the unsigned hexadecimal input. 
    * 
    * @param valueInUnsignedHex  a {@link String} containing the value in unsigned hexadecimal notation 
    * @return      a {@code long} containing the least-significant 64 bits of the value 
    * @throws NumberFormatException if the input {@link String} is empty or contains any nonhexadecimal characters 
    */ 
    public static final long fromUnsignedHex(final String valueInUnsignedHex) { 
    long value = 0; 

    final int hexLength = valueInUnsignedHex.length(); 
    if (hexLength == 0) throw new NumberFormatException("For input string: \"\""); 
    for (int i = Math.max(0, hexLength - 16); i < hexLength; i++) { 
     final char ch = valueInUnsignedHex.charAt(i); 

     if  (ch >= '0' && ch <= '9') value = (value << 4) | (ch - '0'  ); 
     else if (ch >= 'A' && ch <= 'F') value = (value << 4) | (ch - ('A' - 0xaL)); 
     else if (ch >= 'a' && ch <= 'f') value = (value << 4) | (ch - ('a' - 0xaL)); 
     else        throw new NumberFormatException("For input string: \"" + valueInUnsignedHex + "\""); 
    } 

    return value; 
    } 

    public static void main(String[] args) { 
    System.out.println(fromUnsignedHex("d1bc4f7154ac9edb")); 
    } 
} 

Esto produce

-3333702275990511909 
+0

Esto se ve bien, pero en lugar de obtener los valores de los dígitos como lo hizo anteriormente, ¿quizás sería mejor usar Character.digit? http://docs.oracle.com/javase/7/docs/api/java/lang/Character.html#digit(int,%20int) – asieira

+0

'Character.digit' incluye todos los dígitos decimales Unicode, y yo no desea manejar todos ellos, ya que hay varios conjuntos de ellos, algunos de los cuales no están debidamente documentados. – Olathe

+0

Creo que ser capaz de extraer el valor numérico de cualquiera de los posibles dígitos Unicode es una ventaja al hacer que su código sea más portátil y compatible con la internatioalización. Incluso si su proyecto no lo necesita, tal vez los usuarios de desbordamiento de pila se beneficiarían si actualizara su respuesta. Solo mis 2 centavos. – asieira

3

Las respuestas anteriores son excesivamente complejos o fuera de fecha.

Long.parseUnsignedLong(hexstring, 16)

Cuestiones relacionadas