2011-02-09 3 views
0

J'ai un fichier sur le disque que je lis qui a été écrit par le code c/C++. Je sais que j'ai deux entiers non signés de 64 bits à lire, mais Java ne prend pas en charge les entiers non signés, donc la valeur que j'obtiens quand je fais DataInputStream.readLong() est incorrecte. (Ignorez byte-order pour l'instant j'utilise en fait un dérivé de DIS appelé LEDataInputStream que j'ai téléchargé sur le web)C/C++ long long à Java long

Beaucoup de messages ici parlent d'utiliser BigInteger mais le javadoc pour lire un bytearray ne parle que du chargement une réinterprétation bytearray, et les questions semblent centrées sur le fait que certaines personnes vont en dehors des limites positives du type long java, que je serai loin des données que je suis en train de lire.

J'ai un script MATLab/Octave qui lit ces longues valeurs longues sous la forme de deux entiers de 32 bits, puis multiplie et ajoute pour obtenir la réponse qu'il souhaite.

Je suppose que la question est - comment puis-je lire un entier non signé de 64 bits en utilisant BigInteger, ou en utilisant [LE] DataInputStream.XXX?

Merci à l'avance

Répondre

3

Je suggère d'utiliser un code ByteBuffer puis en utilisant par exemple this pour obtenir ce que vous voulez.

+0

Cela semble prometteur, mais je dois implémenter la fonctionnalité de lire la longue moi-même type (car il n'y a pas de méthode pour lire un unsigned long) et le mettre en BigInteger. Je l'ai accepté comme réponse officielle car c'est la plus proche de ce que je voulais –

0

d'abord vous consultez this question

également voir this

maintenant utiliser la classe BigInteger

// Get a byte array 
byte[] bytes = new byte[]{(byte)0x12, (byte)0x0F, (byte)0xF0}; 

// Create a BigInteger using the byte array 
BigInteger bi = new BigInteger(bytes); 

// Format to binary 
String s = bi.toString(2);  // 100100000111111110000 

// Format to octal 
s = bi.toString(8);    // 4407760 

// Format to decimal 
s = bi.toString();    // 1183728 

// Format to hexadecimal 
s = bi.toString(16);   // 120ff0 
if (s.length() % 2 != 0) { 
    // Pad with 0 
    s = "0"+s; 
} 


// Parse binary string 
bi = new BigInteger("100100000111111110000", 2); 

// Parse octal string 
bi = new BigInteger("4407760", 8); 

// Parse decimal string 
bi = new BigInteger("1183728"); 

// Parse hexadecimal string 
bi = new BigInteger("120ff0", 16); 

// Get byte array 
bytes = bi.toByteArray(); 
1

Vous pouvez utiliser un long comme une valeur 64 bits pour stocker des données non signées. Voici un module montrant que la plupart des opérations Unsigned peuvent être effectuées en utilisant le type standard long. Cela dépend vraiment de ce que vous voulez faire avec la valeur que ce soit un problème ou non.

EDIT: Une approche courante pour gérer des nombres non signés est d'élargir le type de données. Cela est plus simple dans la plupart des cas mais pas obligatoire (et pour long en utilisant BigInteger ne rend pas les choses plus simples IMHO)

EDIT2: Quel est le problème avec le code suivant?

long max_unsigned = 0xFFFFFFFFFFFFFFFFl; 
long min_unsigned = 0; 
System.out.println(Unsigned.asString(max_unsigned) + " > " 
     + Unsigned.asString(min_unsigned) + " is " 
     + Unsigned.gt(max_unsigned, min_unsigned)); 

impressions

18446744073709551615 > 0 is true 
+0

Malheureusement, cela ne répond pas complètement à ma requête - les données que j'ai sont déjà sur le disque et ne sont pas écrites par moi, donc je ne peux pas utilise le type java signé, comme quand je le lis depuis le disque, la valeur absolue est fausse! –

+0

@ James, Mais comment est-ce que c'est mal et pouvez-vous faire quelque chose à ce sujet? Je dirais que vous pouvez, sans beaucoup de complexité. À mon humble avis, cela semble seulement impossible parce que vous n'y avez pas pensé. –

+0

@James, j'ai ajouté un exemple qui montre que les valeurs ne sont pas fausses. –